aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp43
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp2
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp14
-rw-r--r--clang/lib/AST/ByteCode/InterpStack.h2
-rw-r--r--clang/lib/AST/ByteCode/Pointer.cpp13
-rw-r--r--clang/lib/AST/ByteCode/Pointer.h6
-rw-r--r--clang/lib/AST/ByteCode/Program.cpp6
-rw-r--r--clang/lib/AST/ByteCode/Program.h3
-rw-r--r--clang/lib/AST/Expr.cpp23
-rw-r--r--clang/lib/AST/ExprObjC.cpp1
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExpr.cpp13
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp7
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.cpp126
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.h2
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp9
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.h5
-rw-r--r--clang/lib/Driver/Driver.cpp13
-rw-r--r--clang/lib/Driver/ToolChains/HIPSPV.cpp9
-rw-r--r--clang/lib/Headers/opencl-c-base.h11
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp8
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp6
-rw-r--r--clang/lib/Sema/SemaOverload.cpp4
-rw-r--r--clang/lib/Sema/SemaStmt.cpp15
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp6
24 files changed, 262 insertions, 85 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 63ac536..d0ddb2e 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1022,7 +1022,8 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
if (classifyPrim(E) != PT_Ptr)
return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);
return true;
- } else if (Op == BO_Sub) {
+ }
+ if (Op == BO_Sub) {
if (!this->emitSubOffset(OffsetType, E))
return false;
@@ -3703,7 +3704,7 @@ bool Compiler<Emitter>::VisitBlockExpr(const BlockExpr *E) {
return true;
const Function *Func = nullptr;
- if (auto F = Ctx.getOrCreateObjCBlock(E))
+ if (const Function *F = Ctx.getOrCreateObjCBlock(E))
Func = F;
if (!Func)
@@ -4288,7 +4289,8 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
return false;
}
return true;
- } else if (ElemType->isRecordType()) {
+ }
+ if (ElemType->isRecordType()) {
const Record *R = getRecord(ElemType);
for (size_t I = 0; I != NumElems; ++I) {
@@ -4302,7 +4304,8 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
return false;
}
return true;
- } else if (ElemType->isArrayType()) {
+ }
+ if (ElemType->isArrayType()) {
for (size_t I = 0; I != NumElems; ++I) {
if (!this->emitConstUint32(I, E))
return false;
@@ -4774,11 +4777,10 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
if (!this->visit(Init))
return false;
return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();
- } else {
+ }
if (!this->visit(Init))
return false;
return this->emitSetLocal(*VarT, Offset, VD);
- }
}
} else {
if (std::optional<unsigned> Offset = this->allocateLocal(
@@ -4805,7 +4807,7 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
assert(!DiscardResult);
if (Val.isInt())
return this->emitConst(Val.getInt(), ValType, E);
- else if (Val.isFloat()) {
+ if (Val.isFloat()) {
APFloat F = Val.getFloat();
return this->emitFloat(F, E);
}
@@ -4816,9 +4818,8 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
APValue::LValueBase Base = Val.getLValueBase();
if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
return this->visit(BaseExpr);
- else if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) {
+ if (const auto *VD = Base.dyn_cast<const ValueDecl *>())
return this->visitDeclRef(VD, E);
- }
} else if (Val.isMemberPointer()) {
if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())
return this->emitGetMemberPtr(MemberDecl, E);
@@ -4854,7 +4855,8 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
}
}
return true;
- } else if (Val.isUnion()) {
+ }
+ if (Val.isUnion()) {
const FieldDecl *UnionField = Val.getUnionField();
const Record *R = this->getRecord(UnionField->getParent());
assert(R);
@@ -4864,7 +4866,8 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
if (!this->visitAPValue(F, T, E))
return false;
return this->emitInitField(T, RF->Offset, E);
- } else if (Val.isArray()) {
+ }
+ if (Val.isArray()) {
const auto *ArrType = T->getAsArrayTypeUnsafe();
QualType ElemType = ArrType->getElementType();
for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {
@@ -4981,12 +4984,10 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
// Calls to replaceable operator new/operator delete.
if (FuncDecl->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
- if (FuncDecl->getDeclName().isAnyOperatorNew()) {
+ if (FuncDecl->getDeclName().isAnyOperatorNew())
return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_new);
- } else {
- assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete);
- return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);
- }
+ assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete);
+ return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);
}
// Explicit calls to trivial destructors
@@ -5455,7 +5456,9 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
return false;
this->emitCleanup();
return this->emitRet(*ReturnType, RS);
- } else if (RE->getType()->isVoidType()) {
+ }
+
+ if (RE->getType()->isVoidType()) {
if (!this->visit(RE))
return false;
} else {
@@ -5500,7 +5503,7 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
if (std::optional<bool> BoolValue = getBoolValue(IS->getCond())) {
if (*BoolValue)
return visitChildStmt(IS->getThen());
- else if (const Stmt *Else = IS->getElse())
+ if (const Stmt *Else = IS->getElse())
return visitChildStmt(Else);
return true;
}
@@ -5992,7 +5995,7 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
if (!this->emitThis(Ctor))
return false;
- auto PVD = Ctor->getParamDecl(0);
+ const ParmVarDecl *PVD = Ctor->getParamDecl(0);
ParamOffset PO = this->Params[PVD]; // Must exist.
if (!this->emitGetParam(PT_Ptr, PO.Offset, Ctor))
@@ -6153,7 +6156,7 @@ bool Compiler<Emitter>::compileUnionAssignmentOperator(
if (!this->emitThis(MD))
return false;
- auto PVD = MD->getParamDecl(0);
+ const ParmVarDecl *PVD = MD->getParamDecl(0);
ParamOffset PO = this->Params[PVD]; // Must exist.
if (!this->emitGetParam(PT_Ptr, PO.Offset, MD))
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 5463aec..224d65c 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -845,7 +845,7 @@ bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return true;
}
-bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
+static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
const SourceLocation &Loc = S.Current->getLocation(OpPC);
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 19d4c0c..3ece7054 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -240,9 +240,9 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
T CB = PB.deref<T>();
if (CA > CB)
return returnResult(1);
- else if (CA < CB)
+ if (CA < CB)
return returnResult(-1);
- else if (CA.isZero() || CB.isZero())
+ if (CA.isZero() || CB.isZero())
return returnResult(0);
});
continue;
@@ -253,7 +253,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
if (CA > CB)
return returnResult(1);
- else if (CA < CB)
+ if (CA < CB)
return returnResult(-1);
if (CA == 0 || CB == 0)
return returnResult(0);
@@ -1048,7 +1048,7 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
PtrArg = ICE->getSubExpr();
}
- if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) {
+ if (const auto *PtrTy = PtrArg->getType()->getAs<PointerType>()) {
QualType PointeeType = PtrTy->getPointeeType();
if (!PointeeType->isIncompleteType() &&
S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) {
@@ -1967,7 +1967,8 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
if (A < B) {
pushInteger(S, -1, Call->getType());
return true;
- } else if (A > B) {
+ }
+ if (A > B) {
pushInteger(S, 1, Call->getType());
return true;
}
@@ -1979,7 +1980,8 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
if (A < B) {
pushInteger(S, -1, Call->getType());
return true;
- } else if (A > B) {
+ }
+ if (A > B) {
pushInteger(S, 1, Call->getType());
return true;
}
diff --git a/clang/lib/AST/ByteCode/InterpStack.h b/clang/lib/AST/ByteCode/InterpStack.h
index 0b76f1d..580494e 100644
--- a/clang/lib/AST/ByteCode/InterpStack.h
+++ b/clang/lib/AST/ByteCode/InterpStack.h
@@ -14,11 +14,9 @@
#define LLVM_CLANG_AST_INTERP_INTERPSTACK_H
#include "FixedPoint.h"
-#include "FunctionPointer.h"
#include "IntegralAP.h"
#include "MemberPointer.h"
#include "PrimType.h"
-#include <memory>
#include <vector>
namespace clang {
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index 4019b74..9341bc1 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -16,6 +16,7 @@
#include "MemberPointer.h"
#include "PrimType.h"
#include "Record.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
@@ -66,14 +67,14 @@ Pointer::~Pointer() {
}
}
-void Pointer::operator=(const Pointer &P) {
+Pointer &Pointer::operator=(const Pointer &P) {
// If the current storage type is Block, we need to remove
// this pointer from the block.
if (isBlockPointer()) {
if (P.isBlockPointer() && this->block() == P.block()) {
Offset = P.Offset;
PointeeStorage.BS.Base = P.PointeeStorage.BS.Base;
- return;
+ return *this;
}
if (Block *Pointee = PointeeStorage.BS.Pointee) {
@@ -101,16 +102,17 @@ void Pointer::operator=(const Pointer &P) {
} else {
assert(false && "Unhandled storage kind");
}
+ return *this;
}
-void Pointer::operator=(Pointer &&P) {
+Pointer &Pointer::operator=(Pointer &&P) {
// If the current storage type is Block, we need to remove
// this pointer from the block.
if (isBlockPointer()) {
if (P.isBlockPointer() && this->block() == P.block()) {
Offset = P.Offset;
PointeeStorage.BS.Base = P.PointeeStorage.BS.Base;
- return;
+ return *this;
}
if (Block *Pointee = PointeeStorage.BS.Pointee) {
@@ -138,6 +140,7 @@ void Pointer::operator=(Pointer &&P) {
} else {
assert(false && "Unhandled storage kind");
}
+ return *this;
}
APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
@@ -603,7 +606,7 @@ bool Pointer::pointsToStringLiteral() const {
return false;
const Expr *E = block()->getDescriptor()->asExpr();
- return E && isa<StringLiteral>(E);
+ return isa_and_nonnull<StringLiteral>(E);
}
std::optional<std::pair<Pointer, Pointer>>
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index d17eba5..059f176 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -120,8 +120,8 @@ public:
Pointer(Block *Pointee, unsigned Base, uint64_t Offset);
~Pointer();
- void operator=(const Pointer &P);
- void operator=(Pointer &&P);
+ Pointer &operator=(const Pointer &P);
+ Pointer &operator=(Pointer &&P);
/// Equality operators are just for tests.
bool operator==(const Pointer &P) const {
@@ -761,7 +761,7 @@ public:
if (Offset < Other.Offset)
return ComparisonCategoryResult::Less;
- else if (Offset > Other.Offset)
+ if (Offset > Other.Offset)
return ComparisonCategoryResult::Greater;
return ComparisonCategoryResult::Equal;
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index 7002724..2421ec4 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -418,7 +418,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
}
return allocateDescriptor(D, *T, MDSize, NumElems, IsConst, IsTemporary,
IsMutable);
- } else {
+ }
// Arrays of composites. In this case, the array is a list of pointers,
// followed by the actual elements.
const Descriptor *ElemDesc = createDescriptor(
@@ -430,7 +430,6 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
return {};
return allocateDescriptor(D, Ty, ElemDesc, MDSize, NumElems, IsConst,
IsTemporary, IsMutable);
- }
}
// Array of unknown bounds - cannot be accessed and pointer arithmetic
@@ -440,14 +439,13 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
if (OptPrimType T = Ctx.classify(ElemTy)) {
return allocateDescriptor(D, *T, MDSize, IsConst, IsTemporary,
Descriptor::UnknownSize{});
- } else {
+ }
const Descriptor *Desc = createDescriptor(
D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary);
if (!Desc)
return nullptr;
return allocateDescriptor(D, Desc, MDSize, IsTemporary,
Descriptor::UnknownSize{});
- }
}
}
diff --git a/clang/lib/AST/ByteCode/Program.h b/clang/lib/AST/ByteCode/Program.h
index 5d9c422..207ceef 100644
--- a/clang/lib/AST/ByteCode/Program.h
+++ b/clang/lib/AST/ByteCode/Program.h
@@ -19,10 +19,7 @@
#include "Record.h"
#include "Source.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PointerUnion.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
-#include <map>
#include <vector>
namespace clang {
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 2e1a9a3..d85655b 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1629,20 +1629,20 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const {
return FnType->getReturnType();
}
-std::pair<const NamedDecl *, const Attr *>
-CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const {
+std::pair<const NamedDecl *, const WarnUnusedResultAttr *>
+Expr::getUnusedResultAttrImpl(const Decl *Callee, QualType ReturnType) {
// If the callee is marked nodiscard, return that attribute
- if (const Decl *D = getCalleeDecl())
- if (const auto *A = D->getAttr<WarnUnusedResultAttr>())
+ if (Callee != nullptr)
+ if (const auto *A = Callee->getAttr<WarnUnusedResultAttr>())
return {nullptr, A};
// If the return type is a struct, union, or enum that is marked nodiscard,
// then return the return type attribute.
- if (const TagDecl *TD = getCallReturnType(Ctx)->getAsTagDecl())
+ if (const TagDecl *TD = ReturnType->getAsTagDecl())
if (const auto *A = TD->getAttr<WarnUnusedResultAttr>())
return {TD, A};
- for (const auto *TD = getCallReturnType(Ctx)->getAs<TypedefType>(); TD;
+ for (const auto *TD = ReturnType->getAs<TypedefType>(); TD;
TD = TD->desugar()->getAs<TypedefType>())
if (const auto *A = TD->getDecl()->getAttr<WarnUnusedResultAttr>())
return {TD->getDecl(), A};
@@ -2844,12 +2844,11 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
return true;
}
- if (const ObjCMethodDecl *MD = ME->getMethodDecl())
- if (MD->hasAttr<WarnUnusedResultAttr>()) {
- WarnE = this;
- Loc = getExprLoc();
- return true;
- }
+ if (ME->hasUnusedResultAttr(Ctx)) {
+ WarnE = this;
+ Loc = getExprLoc();
+ return true;
+ }
return false;
}
diff --git a/clang/lib/AST/ExprObjC.cpp b/clang/lib/AST/ExprObjC.cpp
index 50d3a447..83419a1 100644
--- a/clang/lib/AST/ExprObjC.cpp
+++ b/clang/lib/AST/ExprObjC.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/ComputeDependence.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/AST/Type.h"
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 7ff5f26..64dc1ce 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -949,7 +949,6 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
case CK_Dynamic:
case CK_ToUnion:
case CK_BaseToDerived:
- case CK_LValueBitCast:
case CK_AddressSpaceConversion:
case CK_ObjCObjectLValueCast:
case CK_VectorSplat:
@@ -965,6 +964,18 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
return {};
}
+ case CK_LValueBitCast: {
+ // This must be a reinterpret_cast (or c-style equivalent).
+ const auto *ce = cast<ExplicitCastExpr>(e);
+
+ cgm.emitExplicitCastExprType(ce, this);
+ LValue LV = emitLValue(e->getSubExpr());
+ Address V = LV.getAddress().withElementType(
+ builder, convertTypeForMem(ce->getTypeAsWritten()->getPointeeType()));
+
+ return makeAddrLValue(V, e->getType(), LV.getBaseInfo());
+ }
+
case CK_NoOp: {
// CK_NoOp can model a qualification conversion, which can remove an array
// bound and change the IR type.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 02685a3..a09d739 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -189,8 +189,11 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
}
case CK_LValueBitCast: {
- cgf.cgm.errorNYI("ComplexExprEmitter::emitCast CK_LValueBitCast");
- return {};
+ LValue origLV = cgf.emitLValue(op);
+ Address addr =
+ origLV.getAddress().withElementType(builder, cgf.convertType(destTy));
+ LValue destLV = cgf.makeAddrLValue(addr, destTy);
+ return emitLoadOfLValue(destLV, op->getExprLoc());
}
case CK_LValueToRValueBitCast: {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index b4b95d6..c65d025 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -923,4 +923,130 @@ CIRGenFunction::emitArrayLength(const clang::ArrayType *origArrayType,
return builder.getConstInt(*currSrcLoc, SizeTy, countFromCLAs);
}
+// TODO(cir): Most of this function can be shared between CIRGen
+// and traditional LLVM codegen
+void CIRGenFunction::emitVariablyModifiedType(QualType type) {
+ assert(type->isVariablyModifiedType() &&
+ "Must pass variably modified type to EmitVLASizes!");
+
+ // We're going to walk down into the type and look for VLA
+ // expressions.
+ do {
+ assert(type->isVariablyModifiedType());
+
+ const Type *ty = type.getTypePtr();
+ switch (ty->getTypeClass()) {
+ case Type::CountAttributed:
+ case Type::PackIndexing:
+ case Type::ArrayParameter:
+ case Type::HLSLAttributedResource:
+ case Type::HLSLInlineSpirv:
+ case Type::PredefinedSugar:
+ cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType");
+
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.inc"
+ llvm_unreachable(
+ "dependent type must be resolved before the CIR codegen");
+
+ // These types are never variably-modified.
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::ConstantMatrix:
+ case Type::Record:
+ case Type::Enum:
+ case Type::Using:
+ case Type::TemplateSpecialization:
+ case Type::ObjCTypeParam:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ case Type::BitInt:
+ llvm_unreachable("type class is never variably-modified!");
+
+ case Type::Elaborated:
+ type = cast<clang::ElaboratedType>(ty)->getNamedType();
+ break;
+
+ case Type::Adjusted:
+ type = cast<clang::AdjustedType>(ty)->getAdjustedType();
+ break;
+
+ case Type::Decayed:
+ type = cast<clang::DecayedType>(ty)->getPointeeType();
+ break;
+
+ case Type::Pointer:
+ type = cast<clang::PointerType>(ty)->getPointeeType();
+ break;
+
+ case Type::BlockPointer:
+ type = cast<clang::BlockPointerType>(ty)->getPointeeType();
+ break;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ type = cast<clang::ReferenceType>(ty)->getPointeeType();
+ break;
+
+ case Type::MemberPointer:
+ type = cast<clang::MemberPointerType>(ty)->getPointeeType();
+ break;
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ // Losing element qualification here is fine.
+ type = cast<clang::ArrayType>(ty)->getElementType();
+ break;
+
+ case Type::VariableArray: {
+ cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType VLA");
+ break;
+ }
+
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ type = cast<clang::FunctionType>(ty)->getReturnType();
+ break;
+
+ case Type::Paren:
+ case Type::TypeOf:
+ case Type::UnaryTransform:
+ case Type::Attributed:
+ case Type::BTFTagAttributed:
+ case Type::SubstTemplateTypeParm:
+ case Type::MacroQualified:
+ // Keep walking after single level desugaring.
+ type = type.getSingleStepDesugaredType(getContext());
+ break;
+
+ case Type::Typedef:
+ case Type::Decltype:
+ case Type::Auto:
+ case Type::DeducedTemplateSpecialization:
+ // Stop walking: nothing to do.
+ return;
+
+ case Type::TypeOfExpr:
+ // Stop walking: emit typeof expression.
+ emitIgnoredExpr(cast<clang::TypeOfExprType>(ty)->getUnderlyingExpr());
+ return;
+
+ case Type::Atomic:
+ type = cast<clang::AtomicType>(ty)->getValueType();
+ break;
+
+ case Type::Pipe:
+ type = cast<clang::PipeType>(ty)->getElementType();
+ break;
+ }
+ } while (type->isVariablyModifiedType());
+}
+
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 4891c74..77539d7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1201,6 +1201,8 @@ public:
/// inside a function, including static vars etc.
void emitVarDecl(const clang::VarDecl &d);
+ void emitVariablyModifiedType(QualType ty);
+
mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
/// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 3502705..0724cb1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1208,6 +1208,15 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
return gv;
}
+void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e,
+ CIRGenFunction *cgf) {
+ if (cgf && e->getType()->isVariablyModifiedType())
+ cgf->emitVariablyModifiedType(e->getType());
+
+ assert(!cir::MissingFeatures::generateDebugInfo() &&
+ "emitExplicitCastExprType");
+}
+
void CIRGenModule::emitDeclContext(const DeclContext *dc) {
for (Decl *decl : dc->decls()) {
// Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 16922b1..22519ff 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -252,6 +252,11 @@ public:
getAddrOfGlobal(clang::GlobalDecl gd,
ForDefinition_t isForDefinition = NotForDefinition);
+ /// Emit type info if type of an expression is a variably modified
+ /// type. Also emit proper debug info for cast types.
+ void emitExplicitCastExprType(const ExplicitCastExpr *e,
+ CIRGenFunction *cgf = nullptr);
+
/// Emit code for a single global function or variable declaration. Forward
/// declarations are emitted lazily.
void emitGlobal(clang::GlobalDecl gd);
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 853f694..99de951 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -910,7 +910,7 @@ getSystemOffloadArchs(Compilation &C, Action::OffloadKind Kind) {
SmallVector<std::string> GPUArchs;
if (llvm::ErrorOr<std::string> Executable =
- llvm::sys::findProgramByName(Program)) {
+ llvm::sys::findProgramByName(Program, {C.getDriver().Dir})) {
llvm::SmallVector<StringRef> Args{*Executable};
if (Kind == Action::OFK_HIP)
Args.push_back("--only=amdgpu");
@@ -4919,13 +4919,14 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
}
// HIP code in device-only non-RDC mode will bundle the output if it invoked
- // the linker.
+ // the linker or if the user explicitly requested it.
bool ShouldBundleHIP =
- HIPNoRDC && offloadDeviceOnly() &&
Args.hasFlag(options::OPT_gpu_bundle_output,
- options::OPT_no_gpu_bundle_output, true) &&
- !llvm::any_of(OffloadActions,
- [](Action *A) { return A->getType() != types::TY_Image; });
+ options::OPT_no_gpu_bundle_output, false) ||
+ (HIPNoRDC && offloadDeviceOnly() &&
+ llvm::none_of(OffloadActions, [](Action *A) {
+ return A->getType() != types::TY_Image;
+ }));
// All kinds exit now in device-only mode except for non-RDC mode HIP.
if (offloadDeviceOnly() && !ShouldBundleHIP)
diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp
index 643a67f..62bca04 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp
+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -69,8 +69,17 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand(
// Link LLVM bitcode.
ArgStringList LinkArgs{};
+
for (auto Input : Inputs)
LinkArgs.push_back(Input.getFilename());
+
+ // Add static device libraries using the common helper function.
+ // This handles unbundling archives (.a) containing bitcode bundles.
+ StringRef Arch = getToolChain().getTriple().getArchName();
+ StringRef Target =
+ "generic"; // SPIR-V is generic, no specific target ID like -mcpu
+ tools::AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LinkArgs, Arch,
+ Target, /*IsBitCodeSDL=*/true);
LinkArgs.append({"-o", TempFile});
const char *LlvmLink =
Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
diff --git a/clang/lib/Headers/opencl-c-base.h b/clang/lib/Headers/opencl-c-base.h
index 2b7f504..6206a34 100644
--- a/clang/lib/Headers/opencl-c-base.h
+++ b/clang/lib/Headers/opencl-c-base.h
@@ -697,7 +697,16 @@ template <typename _Tp> struct __remove_address_space<__constant _Tp> {
#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
-int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
+#ifdef __OPENCL_CPP_VERSION__
+#define CLINKAGE extern "C"
+#else
+#define CLINKAGE
+#endif
+
+CLINKAGE int printf(__constant const char *st, ...)
+ __attribute__((format(printf, 1, 2)));
+
+#undef CLINKAGE
#endif
#ifdef cl_intel_device_side_avc_motion_estimation
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index 890567c..6f12ac8 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1760,7 +1760,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Tok, *this, diag::err_feature_check_malformed);
if (!II)
return false;
- else if (II->getBuiltinID() != 0) {
+ unsigned BuiltinID = II->getBuiltinID();
+ if (BuiltinID != 0) {
switch (II->getBuiltinID()) {
case Builtin::BI__builtin_cpu_is:
return getTargetInfo().supportsCpuIs();
@@ -1774,8 +1775,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
// usual allocation and deallocation functions. Required by libc++
return 201802;
default:
+ // __has_builtin should return false for aux builtins.
+ if (getBuiltinInfo().isAuxBuiltinID(BuiltinID))
+ return false;
return Builtin::evaluateRequiredTargetFeatures(
- getBuiltinInfo().getRequiredFeatures(II->getBuiltinID()),
+ getBuiltinInfo().getRequiredFeatures(BuiltinID),
getTargetInfo().getTargetOpts().FeatureMap);
}
return true;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index a4e8de4..16b18bc 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4805,10 +4805,10 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
static void handleNonStringAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// This only applies to fields and variable declarations which have an array
- // type.
+ // type or pointer type, with character elements.
QualType QT = cast<ValueDecl>(D)->getType();
- if (!QT->isArrayType() ||
- !QT->getBaseElementTypeUnsafe()->isAnyCharacterType()) {
+ if ((!QT->isArrayType() && !QT->isPointerType()) ||
+ !QT->getPointeeOrArrayElementType()->isAnyCharacterType()) {
S.Diag(D->getBeginLoc(), diag::warn_attribute_non_character_array)
<< AL << AL.isRegularKeywordAttribute() << QT << AL.getRange();
return;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 5dd5b49..76e189d 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -8042,8 +8042,8 @@ static void AddTemplateOverloadCandidateImmediately(
Candidate.IgnoreObjectArgument =
isa<CXXMethodDecl>(Candidate.Function) &&
- cast<CXXMethodDecl>(Candidate.Function)
- ->isImplicitObjectMemberFunction() &&
+ !cast<CXXMethodDecl>(Candidate.Function)
+ ->isExplicitObjectMemberFunction() &&
!isa<CXXConstructorDecl>(Candidate.Function);
Candidate.ExplicitCallArguments = Args.size();
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index f85826a..3f89843 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -295,8 +295,7 @@ void DiagnoseUnused(Sema &S, const Expr *E, std::optional<unsigned> DiagID) {
return;
auto [OffendingDecl, A] = CE->getUnusedResultAttr(S.Context);
- if (DiagnoseNoDiscard(S, OffendingDecl,
- cast_or_null<WarnUnusedResultAttr>(A), Loc, R1, R2,
+ if (DiagnoseNoDiscard(S, OffendingDecl, A, Loc, R1, R2,
/*isCtor=*/false))
return;
@@ -344,13 +343,11 @@ void DiagnoseUnused(Sema &S, const Expr *E, std::optional<unsigned> DiagID) {
S.Diag(Loc, diag::err_arc_unused_init_message) << R1;
return;
}
- const ObjCMethodDecl *MD = ME->getMethodDecl();
- if (MD) {
- if (DiagnoseNoDiscard(S, nullptr, MD->getAttr<WarnUnusedResultAttr>(),
- Loc, R1, R2,
- /*isCtor=*/false))
- return;
- }
+
+ auto [OffendingDecl, A] = ME->getUnusedResultAttr(S.Context);
+ if (DiagnoseNoDiscard(S, OffendingDecl, A, Loc, R1, R2,
+ /*isCtor=*/false))
+ return;
} else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
const Expr *Source = POE->getSyntacticForm();
// Handle the actually selected call of an OpenMP specialized call.
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index a7704da..369d619 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -2693,7 +2693,7 @@ void MallocChecker::HandleUseAfterFree(CheckerContext &C, SourceRange Range,
Frontend->UseFreeBug,
AF.Kind == AF_InnerBuffer
? "Inner pointer of container used after re/deallocation"
- : "Use of memory after it is freed",
+ : "Use of memory after it is released",
N);
R->markInteresting(Sym);
@@ -2721,8 +2721,8 @@ void MallocChecker::HandleDoubleFree(CheckerContext &C, SourceRange Range,
if (ExplodedNode *N = C.generateErrorNode()) {
auto R = std::make_unique<PathSensitiveBugReport>(
Frontend->DoubleFreeBug,
- (Released ? "Attempt to free released memory"
- : "Attempt to free non-owned memory"),
+ (Released ? "Attempt to release already released memory"
+ : "Attempt to release non-owned memory"),
N);
if (Range.isValid())
R->addRange(Range);