diff options
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 1164 |
1 files changed, 709 insertions, 455 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 73ddbc62482d..399e7e13c445 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -14,9 +14,11 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/ComputeDependence.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DependenceFlags.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" @@ -242,6 +244,7 @@ static void AssertResultStorageKind(ConstantExpr::ResultStorageKind Kind) { assert((Kind == ConstantExpr::RSK_APValue || Kind == ConstantExpr::RSK_Int64 || Kind == ConstantExpr::RSK_None) && "Invalid StorageKind Value"); + (void)Kind; } ConstantExpr::ResultStorageKind @@ -266,29 +269,31 @@ ConstantExpr::getStorageKind(const Type *T, const ASTContext &Context) { return ConstantExpr::RSK_APValue; } -void ConstantExpr::DefaultInit(ResultStorageKind StorageKind) { +ConstantExpr::ConstantExpr(Expr *SubExpr, ResultStorageKind StorageKind, + bool IsImmediateInvocation) + : FullExpr(ConstantExprClass, SubExpr) { ConstantExprBits.ResultKind = StorageKind; ConstantExprBits.APValueKind = APValue::None; + ConstantExprBits.IsUnsigned = false; + ConstantExprBits.BitWidth = 0; ConstantExprBits.HasCleanup = false; + ConstantExprBits.IsImmediateInvocation = IsImmediateInvocation; + if (StorageKind == ConstantExpr::RSK_APValue) ::new (getTrailingObjects<APValue>()) APValue(); } -ConstantExpr::ConstantExpr(Expr *subexpr, ResultStorageKind StorageKind) - : FullExpr(ConstantExprClass, subexpr) { - DefaultInit(StorageKind); -} - ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E, - ResultStorageKind StorageKind) { + ResultStorageKind StorageKind, + bool IsImmediateInvocation) { assert(!isa<ConstantExpr>(E)); AssertResultStorageKind(StorageKind); + unsigned Size = totalSizeToAlloc<APValue, uint64_t>( StorageKind == ConstantExpr::RSK_APValue, StorageKind == ConstantExpr::RSK_Int64); void *Mem = Context.Allocate(Size, alignof(ConstantExpr)); - ConstantExpr *Self = new (Mem) ConstantExpr(E, StorageKind); - return Self; + return new (Mem) ConstantExpr(E, StorageKind, IsImmediateInvocation); } ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E, @@ -299,25 +304,27 @@ ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E, return Self; } -ConstantExpr::ConstantExpr(ResultStorageKind StorageKind, EmptyShell Empty) +ConstantExpr::ConstantExpr(EmptyShell Empty, ResultStorageKind StorageKind) : FullExpr(ConstantExprClass, Empty) { - DefaultInit(StorageKind); + ConstantExprBits.ResultKind = StorageKind; + + if (StorageKind == ConstantExpr::RSK_APValue) + ::new (getTrailingObjects<APValue>()) APValue(); } ConstantExpr *ConstantExpr::CreateEmpty(const ASTContext &Context, - ResultStorageKind StorageKind, - EmptyShell Empty) { + ResultStorageKind StorageKind) { AssertResultStorageKind(StorageKind); + unsigned Size = totalSizeToAlloc<APValue, uint64_t>( StorageKind == ConstantExpr::RSK_APValue, StorageKind == ConstantExpr::RSK_Int64); void *Mem = Context.Allocate(Size, alignof(ConstantExpr)); - ConstantExpr *Self = new (Mem) ConstantExpr(StorageKind, Empty); - return Self; + return new (Mem) ConstantExpr(EmptyShell(), StorageKind); } void ConstantExpr::MoveIntoResult(APValue &Value, const ASTContext &Context) { - assert(getStorageKind(Value) == ConstantExprBits.ResultKind && + assert((unsigned)getStorageKind(Value) <= ConstantExprBits.ResultKind && "Invalid storage for this value kind"); ConstantExprBits.APValueKind = Value.getKind(); switch (ConstantExprBits.ResultKind) { @@ -352,6 +359,8 @@ llvm::APSInt ConstantExpr::getResultAsAPSInt() const { } APValue ConstantExpr::getAPValueResult() const { + assert(hasAPValueResult()); + switch (ConstantExprBits.ResultKind) { case ConstantExpr::RSK_APValue: return APValueResult(); @@ -365,125 +374,12 @@ APValue ConstantExpr::getAPValueResult() const { llvm_unreachable("invalid ResultKind"); } -/// Compute the type-, value-, and instantiation-dependence of a -/// declaration reference -/// based on the declaration being referenced. -static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D, - QualType T, bool &TypeDependent, - bool &ValueDependent, - bool &InstantiationDependent) { - TypeDependent = false; - ValueDependent = false; - InstantiationDependent = false; - - // (TD) C++ [temp.dep.expr]p3: - // An id-expression is type-dependent if it contains: - // - // and - // - // (VD) C++ [temp.dep.constexpr]p2: - // An identifier is value-dependent if it is: - - // (TD) - an identifier that was declared with dependent type - // (VD) - a name declared with a dependent type, - if (T->isDependentType()) { - TypeDependent = true; - ValueDependent = true; - InstantiationDependent = true; - return; - } else if (T->isInstantiationDependentType()) { - InstantiationDependent = true; - } - - // (TD) - a conversion-function-id that specifies a dependent type - if (D->getDeclName().getNameKind() - == DeclarationName::CXXConversionFunctionName) { - QualType T = D->getDeclName().getCXXNameType(); - if (T->isDependentType()) { - TypeDependent = true; - ValueDependent = true; - InstantiationDependent = true; - return; - } - - if (T->isInstantiationDependentType()) - InstantiationDependent = true; - } - - // (VD) - the name of a non-type template parameter, - if (isa<NonTypeTemplateParmDecl>(D)) { - ValueDependent = true; - InstantiationDependent = true; - return; - } - - // (VD) - a constant with integral or enumeration type and is - // initialized with an expression that is value-dependent. - // (VD) - a constant with literal type and is initialized with an - // expression that is value-dependent [C++11]. - // (VD) - FIXME: Missing from the standard: - // - an entity with reference type and is initialized with an - // expression that is value-dependent [C++11] - if (VarDecl *Var = dyn_cast<VarDecl>(D)) { - if ((Ctx.getLangOpts().CPlusPlus11 ? - Var->getType()->isLiteralType(Ctx) : - Var->getType()->isIntegralOrEnumerationType()) && - (Var->getType().isConstQualified() || - Var->getType()->isReferenceType())) { - if (const Expr *Init = Var->getAnyInitializer()) - if (Init->isValueDependent()) { - ValueDependent = true; - InstantiationDependent = true; - } - } - - // (VD) - FIXME: Missing from the standard: - // - a member function or a static data member of the current - // instantiation - if (Var->isStaticDataMember() && - Var->getDeclContext()->isDependentContext()) { - ValueDependent = true; - InstantiationDependent = true; - TypeSourceInfo *TInfo = Var->getFirstDecl()->getTypeSourceInfo(); - if (TInfo->getType()->isIncompleteArrayType()) - TypeDependent = true; - } - - return; - } - - // (VD) - FIXME: Missing from the standard: - // - a member function or a static data member of the current - // instantiation - if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) { - ValueDependent = true; - InstantiationDependent = true; - } -} - -void DeclRefExpr::computeDependence(const ASTContext &Ctx) { - bool TypeDependent = false; - bool ValueDependent = false; - bool InstantiationDependent = false; - computeDeclRefDependence(Ctx, getDecl(), getType(), TypeDependent, - ValueDependent, InstantiationDependent); - - ExprBits.TypeDependent |= TypeDependent; - ExprBits.ValueDependent |= ValueDependent; - ExprBits.InstantiationDependent |= InstantiationDependent; - - // Is the declaration a parameter pack? - if (getDecl()->isParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; -} - DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T, ExprValueKind VK, SourceLocation L, const DeclarationNameLoc &LocInfo, NonOdrUseReason NOUR) - : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), - D(D), DNLoc(LocInfo) { + : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D), DNLoc(LocInfo) { DeclRefExprBits.HasQualifier = false; DeclRefExprBits.HasTemplateKWAndArgsInfo = false; DeclRefExprBits.HasFoundDecl = false; @@ -492,7 +388,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, RefersToEnclosingVariableOrCapture; DeclRefExprBits.NonOdrUseReason = NOUR; DeclRefExprBits.Loc = L; - computeDependence(Ctx); + setDependence(computeDependence(this, Ctx)); } DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, @@ -502,19 +398,13 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK, NonOdrUseReason NOUR) - : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), - D(D), DNLoc(NameInfo.getInfo()) { + : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D), + DNLoc(NameInfo.getInfo()) { DeclRefExprBits.Loc = NameInfo.getLoc(); DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0; - if (QualifierLoc) { + if (QualifierLoc) new (getTrailingObjects<NestedNameSpecifierLoc>()) NestedNameSpecifierLoc(QualifierLoc); - auto *NNS = QualifierLoc.getNestedNameSpecifier(); - if (NNS->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (NNS->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - } DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0; if (FoundD) *getTrailingObjects<NamedDecl *>() = FoundD; @@ -524,22 +414,18 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, RefersToEnclosingVariableOrCapture; DeclRefExprBits.NonOdrUseReason = NOUR; if (TemplateArgs) { - bool Dependent = false; - bool InstantiationDependent = false; - bool ContainsUnexpandedParameterPack = false; + auto Deps = TemplateArgumentDependence::None; getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(), - Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); - assert(!Dependent && "built a DeclRefExpr with dependent template args"); - ExprBits.InstantiationDependent |= InstantiationDependent; - ExprBits.ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack; + Deps); + assert(!(Deps & TemplateArgumentDependence::Dependent) && + "built a DeclRefExpr with dependent template args"); } else if (TemplateKWLoc.isValid()) { getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( TemplateKWLoc); } DeclRefExprBits.HadMultipleCandidates = 0; - - computeDependence(Ctx); + setDependence(computeDependence(this, Ctx)); } DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, @@ -611,10 +497,7 @@ SourceLocation DeclRefExpr::getEndLoc() const { PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, StringLiteral *SL) - : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary, - FNTy->isDependentType(), FNTy->isDependentType(), - FNTy->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false) { + : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary) { PredefinedExprBits.Kind = IK; assert((getIdentKind() == IK) && "IdentKind do not fit in PredefinedExprBitfields!"); @@ -623,6 +506,35 @@ PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, PredefinedExprBits.Loc = L; if (HasFunctionName) setFunctionName(SL); + setDependence(computeDependence(this)); +} + +PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FnTy, IdentKind IK, + TypeSourceInfo *Info) + : Expr(PredefinedExprClass, FnTy, VK_LValue, OK_Ordinary) { + PredefinedExprBits.Kind = IK; + assert((getIdentKind() == IK) && + "IdentKind do not fit in PredefinedExprBitFields!"); + assert(IK == UniqueStableNameType && + "Constructor only valid with UniqueStableNameType"); + PredefinedExprBits.HasFunctionName = false; + PredefinedExprBits.Loc = L; + setTypeSourceInfo(Info); + setDependence(computeDependence(this)); +} + +PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FnTy, IdentKind IK, + Expr *E) + : Expr(PredefinedExprClass, FnTy, VK_LValue, OK_Ordinary) { + PredefinedExprBits.Kind = IK; + assert((getIdentKind() == IK) && + "IdentKind do not fit in PredefinedExprBitFields!"); + assert(IK == UniqueStableNameExpr && + "Constructor only valid with UniqueStableNameExpr"); + PredefinedExprBits.HasFunctionName = false; + PredefinedExprBits.Loc = L; + setExpr(E); + setDependence(computeDependence(this)); } PredefinedExpr::PredefinedExpr(EmptyShell Empty, bool HasFunctionName) @@ -634,15 +546,44 @@ PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L, QualType FNTy, IdentKind IK, StringLiteral *SL) { bool HasFunctionName = SL != nullptr; - void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName), - alignof(PredefinedExpr)); + void *Mem = Ctx.Allocate( + totalSizeToAlloc<Stmt *, Expr *, TypeSourceInfo *>(HasFunctionName, 0, 0), + alignof(PredefinedExpr)); return new (Mem) PredefinedExpr(L, FNTy, IK, SL); } +PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L, + QualType FNTy, IdentKind IK, + StringLiteral *SL, + TypeSourceInfo *Info) { + assert(IK == UniqueStableNameType && "Only valid with UniqueStableNameType"); + bool HasFunctionName = SL != nullptr; + void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *, Expr *, TypeSourceInfo *>( + HasFunctionName, 0, !HasFunctionName), + alignof(PredefinedExpr)); + if (HasFunctionName) + return new (Mem) PredefinedExpr(L, FNTy, IK, SL); + return new (Mem) PredefinedExpr(L, FNTy, IK, Info); +} + +PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L, + QualType FNTy, IdentKind IK, + StringLiteral *SL, Expr *E) { + assert(IK == UniqueStableNameExpr && "Only valid with UniqueStableNameExpr"); + bool HasFunctionName = SL != nullptr; + void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *, Expr *, TypeSourceInfo *>( + HasFunctionName, !HasFunctionName, 0), + alignof(PredefinedExpr)); + if (HasFunctionName) + return new (Mem) PredefinedExpr(L, FNTy, IK, SL); + return new (Mem) PredefinedExpr(L, FNTy, IK, E); +} + PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx, bool HasFunctionName) { - void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName), - alignof(PredefinedExpr)); + void *Mem = Ctx.Allocate( + totalSizeToAlloc<Stmt *, Expr *, TypeSourceInfo *>(HasFunctionName, 0, 0), + alignof(PredefinedExpr)); return new (Mem) PredefinedExpr(EmptyShell(), HasFunctionName); } @@ -662,12 +603,28 @@ StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) { return "__FUNCSIG__"; case LFuncSig: return "L__FUNCSIG__"; + case UniqueStableNameType: + case UniqueStableNameExpr: + return "__builtin_unique_stable_name"; case PrettyFunctionNoVirtual: break; } llvm_unreachable("Unknown ident kind for PredefinedExpr"); } +std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentKind IK, + QualType Ty) { + std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create( + Context, Context.getDiagnostics(), /*IsUniqueNameMangler*/ true)}; + + Ty = Ty.getCanonicalType(); + + SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + Ctx->mangleTypeName(Ty, Out); + return std::string(Buffer.str()); +} + // FIXME: Maybe this should use DeclPrinter with a special "print predefined // expr" policy instead. std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) { @@ -681,18 +638,22 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) { if (MC->shouldMangleDeclName(ND)) { SmallString<256> Buffer; llvm::raw_svector_ostream Out(Buffer); + GlobalDecl GD; if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(ND)) - MC->mangleCXXCtor(CD, Ctor_Base, Out); + GD = GlobalDecl(CD, Ctor_Base); else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(ND)) - MC->mangleCXXDtor(DD, Dtor_Base, Out); + GD = GlobalDecl(DD, Dtor_Base); + else if (ND->hasAttr<CUDAGlobalAttr>()) + GD = GlobalDecl(cast<FunctionDecl>(ND)); else - MC->mangleName(ND, Out); + GD = GlobalDecl(ND); + MC->mangleName(GD, Out); if (!Buffer.empty() && Buffer.front() == '\01') - return Buffer.substr(1); - return Buffer.str(); + return std::string(Buffer.substr(1)); + return std::string(Buffer.str()); } else - return ND->getIdentifier()->getName(); + return std::string(ND->getIdentifier()->getName()); } return ""; } @@ -711,7 +672,7 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) { Out << ComputeName(IK, DCBlock); else if (auto *DCDecl = dyn_cast<Decl>(DC)) Out << ComputeName(IK, DCDecl) << "_block_invoke"; - return Out.str(); + return std::string(Out.str()); } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) { if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual && @@ -856,7 +817,7 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) { Out << Proto; - return Name.str().str(); + return std::string(Name); } if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(CurrentDecl)) { for (const DeclContext *DC = CD->getParent(); DC; DC = DC->getParent()) @@ -887,7 +848,7 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) { MD->getSelector().print(Out); Out << ']'; - return Name.str().str(); + return std::string(Name); } if (isa<TranslationUnitDecl>(CurrentDecl) && IK == PrettyFunction) { // __PRETTY_FUNCTION__ -> "top level", the others produce an empty string. @@ -915,13 +876,12 @@ void APNumericStorage::setIntValue(const ASTContext &C, IntegerLiteral::IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l) - : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false, - false, false), - Loc(l) { + : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary), Loc(l) { assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); assert(V.getBitWidth() == C.getIntWidth(type) && "Integer type is not the correct size for constant."); setValue(C, V); + setDependence(ExprDependence::None); } IntegerLiteral * @@ -938,13 +898,13 @@ IntegerLiteral::Create(const ASTContext &C, EmptyShell Empty) { FixedPointLiteral::FixedPointLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l, unsigned Scale) - : Expr(FixedPointLiteralClass, type, VK_RValue, OK_Ordinary, false, false, - false, false), - Loc(l), Scale(Scale) { + : Expr(FixedPointLiteralClass, type, VK_RValue, OK_Ordinary), Loc(l), + Scale(Scale) { assert(type->isFixedPointType() && "Illegal type in FixedPointLiteral"); assert(V.getBitWidth() == C.getTypeInfo(type).Width && "Fixed point type is not the correct size for constant."); setValue(C, V); + setDependence(ExprDependence::None); } FixedPointLiteral *FixedPointLiteral::CreateFromRawInt(const ASTContext &C, @@ -955,6 +915,11 @@ FixedPointLiteral *FixedPointLiteral::CreateFromRawInt(const ASTContext &C, return new (C) FixedPointLiteral(C, V, type, l, Scale); } +FixedPointLiteral *FixedPointLiteral::Create(const ASTContext &C, + EmptyShell Empty) { + return new (C) FixedPointLiteral(Empty); +} + std::string FixedPointLiteral::getValueAsString(unsigned Radix) const { // Currently the longest decimal number that can be printed is the max for an // unsigned long _Accum: 4294967295.99999999976716935634613037109375 @@ -962,16 +927,16 @@ std::string FixedPointLiteral::getValueAsString(unsigned Radix) const { SmallString<64> S; FixedPointValueToString( S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale); - return S.str(); + return std::string(S.str()); } FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) - : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false, - false, false), Loc(L) { + : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary), Loc(L) { setSemantics(V.getSemantics()); FloatingLiteralBits.IsExact = isexact; setValue(C, V); + setDependence(ExprDependence::None); } FloatingLiteral::FloatingLiteral(const ASTContext &C, EmptyShell Empty) @@ -1031,8 +996,7 @@ StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated) - : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false, - false) { + : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary) { assert(Ctx.getAsConstantArrayType(Ty) && "StringLiteral must be of constant array type!"); unsigned CharByteWidth = mapCharByteWidth(Ctx.getTargetInfo(), Kind); @@ -1071,6 +1035,8 @@ StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str, // Initialize the trailing array of char holding the string data. std::memcpy(getTrailingObjects<char>(), Str.data(), ByteLength); + + setDependence(ExprDependence::None); } StringLiteral::StringLiteral(EmptyShell Empty, unsigned NumConcatenated, @@ -1339,10 +1305,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, unsigned MinNumArgs, ADLCallKind UsesADL) - : Expr(SC, Ty, VK, OK_Ordinary, Fn->isTypeDependent(), - Fn->isValueDependent(), Fn->isInstantiationDependent(), - Fn->containsUnexpandedParameterPack()), - RParenLoc(RParenLoc) { + : Expr(SC, Ty, VK, OK_Ordinary), RParenLoc(RParenLoc) { NumArgs = std::max<unsigned>(Args.size(), MinNumArgs); unsigned NumPreArgs = PreArgs.size(); CallExprBits.NumPreArgs = NumPreArgs; @@ -1356,17 +1319,14 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, CallExprBits.UsesADL = static_cast<bool>(UsesADL); setCallee(Fn); - for (unsigned I = 0; I != NumPreArgs; ++I) { - updateDependenciesFromArg(PreArgs[I]); + for (unsigned I = 0; I != NumPreArgs; ++I) setPreArg(I, PreArgs[I]); - } - for (unsigned I = 0; I != Args.size(); ++I) { - updateDependenciesFromArg(Args[I]); + for (unsigned I = 0; I != Args.size(); ++I) setArg(I, Args[I]); - } - for (unsigned I = Args.size(); I != NumArgs; ++I) { + for (unsigned I = Args.size(); I != NumArgs; ++I) setArg(I, nullptr); - } + + setDependence(computeDependence(this, PreArgs)); } CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, @@ -1400,7 +1360,8 @@ CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty, assert(!(reinterpret_cast<uintptr_t>(Mem) % alignof(CallExpr)) && "Misaligned memory in CallExpr::CreateTemporary!"); return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty, - VK, RParenLoc, /*MinNumArgs=*/0, UsesADL); + VK, RParenLoc, + /*MinNumArgs=*/0, UsesADL); } CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, @@ -1429,33 +1390,31 @@ unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) { } } -void CallExpr::updateDependenciesFromArg(Expr *Arg) { - if (Arg->isTypeDependent()) - ExprBits.TypeDependent = true; - if (Arg->isValueDependent()) - ExprBits.ValueDependent = true; - if (Arg->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (Arg->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; -} - Decl *Expr::getReferencedDeclOfCallee() { Expr *CEE = IgnoreParenImpCasts(); - while (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) { - CEE = NTTP->getReplacement()->IgnoreParenCasts(); + while (SubstNonTypeTemplateParmExpr *NTTP = + dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) { + CEE = NTTP->getReplacement()->IgnoreParenImpCasts(); } // If we're calling a dereference, look at the pointer instead. - if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) { - if (BO->isPtrMemOp()) - CEE = BO->getRHS()->IgnoreParenCasts(); - } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(CEE)) { - if (UO->getOpcode() == UO_Deref) - CEE = UO->getSubExpr()->IgnoreParenCasts(); + while (true) { + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) { + if (BO->isPtrMemOp()) { + CEE = BO->getRHS()->IgnoreParenImpCasts(); + continue; + } + } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(CEE)) { + if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf || + UO->getOpcode() == UO_Plus) { + CEE = UO->getSubExpr()->IgnoreParenImpCasts(); + continue; + } + } + break; } + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) return DRE->getDecl(); if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE)) @@ -1466,28 +1425,11 @@ Decl *Expr::getReferencedDeclOfCallee() { return nullptr; } -/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID. If -/// not, return 0. +/// If this is a call to a builtin, return the builtin ID. If not, return 0. unsigned CallExpr::getBuiltinCallee() const { - // All simple function calls (e.g. func()) are implicitly cast to pointer to - // function. As a result, we try and obtain the DeclRefExpr from the - // ImplicitCastExpr. - const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee()); - if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()). - return 0; - - const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr()); - if (!DRE) - return 0; - - const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()); - if (!FDecl) - return 0; - - if (!FDecl->getIdentifier()) - return 0; - - return FDecl->getBuiltinID(); + auto *FDecl = + dyn_cast_or_null<FunctionDecl>(getCallee()->getReferencedDeclOfCallee()); + return FDecl ? FDecl->getBuiltinID() : 0; } bool CallExpr::isUnevaluatedBuiltinCall(const ASTContext &Ctx) const { @@ -1569,28 +1511,17 @@ OffsetOfExpr *OffsetOfExpr::CreateEmpty(const ASTContext &C, OffsetOfExpr::OffsetOfExpr(const ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, - ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs, + ArrayRef<OffsetOfNode> comps, ArrayRef<Expr *> exprs, SourceLocation RParenLoc) - : Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary, - /*TypeDependent=*/false, - /*ValueDependent=*/tsi->getType()->isDependentType(), - tsi->getType()->isInstantiationDependentType(), - tsi->getType()->containsUnexpandedParameterPack()), - OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi), - NumComps(comps.size()), NumExprs(exprs.size()) -{ - for (unsigned i = 0; i != comps.size(); ++i) { + : Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary), + OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi), + NumComps(comps.size()), NumExprs(exprs.size()) { + for (unsigned i = 0; i != comps.size(); ++i) setComponent(i, comps[i]); - } - - for (unsigned i = 0; i != exprs.size(); ++i) { - if (exprs[i]->isTypeDependent() || exprs[i]->isValueDependent()) - ExprBits.ValueDependent = true; - if (exprs[i]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - + for (unsigned i = 0; i != exprs.size(); ++i) setIndexExpr(i, exprs[i]); - } + + setDependence(computeDependence(this)); } IdentifierInfo *OffsetOfNode::getFieldName() const { @@ -1604,39 +1535,15 @@ IdentifierInfo *OffsetOfNode::getFieldName() const { UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr( UnaryExprOrTypeTrait ExprKind, Expr *E, QualType resultType, SourceLocation op, SourceLocation rp) - : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, - false, // Never type-dependent (C++ [temp.dep.expr]p3). - // Value-dependent if the argument is type-dependent. - E->isTypeDependent(), E->isInstantiationDependent(), - E->containsUnexpandedParameterPack()), + : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary), OpLoc(op), RParenLoc(rp) { + assert(ExprKind <= UETT_Last && "invalid enum value!"); UnaryExprOrTypeTraitExprBits.Kind = ExprKind; + assert(static_cast<unsigned>(ExprKind) == UnaryExprOrTypeTraitExprBits.Kind && + "UnaryExprOrTypeTraitExprBits.Kind overflow!"); UnaryExprOrTypeTraitExprBits.IsType = false; Argument.Ex = E; - - // Check to see if we are in the situation where alignof(decl) should be - // dependent because decl's alignment is dependent. - if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) { - if (!isValueDependent() || !isInstantiationDependent()) { - E = E->IgnoreParens(); - - const ValueDecl *D = nullptr; - if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) - D = DRE->getDecl(); - else if (const auto *ME = dyn_cast<MemberExpr>(E)) - D = ME->getMemberDecl(); - - if (D) { - for (const auto *I : D->specific_attrs<AlignedAttr>()) { - if (I->isAlignmentDependent()) { - setValueDependent(true); - setInstantiationDependent(true); - break; - } - } - } - } - } + setDependence(computeDependence(this)); } MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, @@ -1644,11 +1551,8 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) - : Expr(MemberExprClass, T, VK, OK, Base->isTypeDependent(), - Base->isValueDependent(), Base->isInstantiationDependent(), - Base->containsUnexpandedParameterPack()), - Base(Base), MemberDecl(MemberDecl), MemberDNLoc(NameInfo.getInfo()), - MemberLoc(NameInfo.getLoc()) { + : Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl), + MemberDNLoc(NameInfo.getInfo()), MemberLoc(NameInfo.getLoc()) { assert(!NameInfo.getName() || MemberDecl->getDeclName() == NameInfo.getName()); MemberExprBits.IsArrow = IsArrow; @@ -1657,6 +1561,7 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, MemberExprBits.HadMultipleCandidates = false; MemberExprBits.NonOdrUseReason = NOUR; MemberExprBits.OperatorLoc = OperatorLoc; + setDependence(computeDependence(this)); } MemberExpr *MemberExpr::Create( @@ -1678,25 +1583,15 @@ MemberExpr *MemberExpr::Create( MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, NameInfo, T, VK, OK, NOUR); - if (isa<FieldDecl>(MemberDecl)) { - DeclContext *DC = MemberDecl->getDeclContext(); - // dyn_cast_or_null is used to handle objC variables which do not - // have a declaration context. - CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC); - if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC)) - E->setTypeDependent(T->isDependentType()); - } - + // FIXME: remove remaining dependence computation to computeDependence(). + auto Deps = E->getDependence(); if (HasQualOrFound) { // FIXME: Wrong. We should be looking at the member declaration we found. - if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) { - E->setValueDependent(true); - E->setTypeDependent(true); - E->setInstantiationDependent(true); - } + if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) + Deps |= ExprDependence::TypeValueInstantiation; else if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) - E->setInstantiationDependent(true); + Deps |= ExprDependence::Instantiation; E->MemberExprBits.HasQualifierOrFoundDecl = true; @@ -1710,19 +1605,17 @@ MemberExpr *MemberExpr::Create( TemplateArgs || TemplateKWLoc.isValid(); if (TemplateArgs) { - bool Dependent = false; - bool InstantiationDependent = false; - bool ContainsUnexpandedParameterPack = false; + auto TemplateArgDeps = TemplateArgumentDependence::None; E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( TemplateKWLoc, *TemplateArgs, - E->getTrailingObjects<TemplateArgumentLoc>(), Dependent, - InstantiationDependent, ContainsUnexpandedParameterPack); - if (InstantiationDependent) - E->setInstantiationDependent(true); + E->getTrailingObjects<TemplateArgumentLoc>(), TemplateArgDeps); + if (TemplateArgDeps & TemplateArgumentDependence::Instantiation) + Deps |= ExprDependence::Instantiation; } else if (TemplateKWLoc.isValid()) { E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( TemplateKWLoc); } + E->setDependence(Deps); return E; } @@ -1823,12 +1716,13 @@ bool CastExpr::CastConsistency() const { auto Ty = getType(); auto SETy = getSubExpr()->getType(); assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy)); - if (isRValue()) { + if (isRValue() && !Ty->isDependentType() && !SETy->isDependentType()) { Ty = Ty->getPointeeType(); SETy = SETy->getPointeeType(); } - assert(!Ty.isNull() && !SETy.isNull() && - Ty.getAddressSpace() != SETy.getAddressSpace()); + assert((Ty->isDependentType() || SETy->isDependentType()) || + (!Ty.isNull() && !SETy.isNull() && + Ty.getAddressSpace() != SETy.getAddressSpace())); goto CheckNoBasePath; } // These should not have an inheritance path. @@ -2163,9 +2057,10 @@ SourceLocExpr::SourceLocExpr(const ASTContext &Ctx, IdentKind Kind, SourceLocation BLoc, SourceLocation RParenLoc, DeclContext *ParentContext) : Expr(SourceLocExprClass, getDecayedSourceLocExprType(Ctx, Kind), - VK_RValue, OK_Ordinary, false, false, false, false), + VK_RValue, OK_Ordinary), BuiltinLoc(BLoc), RParenLoc(RParenLoc), ParentContext(ParentContext) { SourceLocExprBits.Kind = Kind; + setDependence(ExprDependence::None); } StringRef SourceLocExpr::getBuiltinStr() const { @@ -2229,25 +2124,14 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx, } InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc, - ArrayRef<Expr*> initExprs, SourceLocation rbraceloc) - : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, - false, false), - InitExprs(C, initExprs.size()), - LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(nullptr, true) -{ + ArrayRef<Expr *> initExprs, SourceLocation rbraceloc) + : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary), + InitExprs(C, initExprs.size()), LBraceLoc(lbraceloc), + RBraceLoc(rbraceloc), AltForm(nullptr, true) { sawArrayRangeDesignator(false); - for (unsigned I = 0; I != initExprs.size(); ++I) { - if (initExprs[I]->isTypeDependent()) - ExprBits.TypeDependent = true; - if (initExprs[I]->isValueDependent()) - ExprBits.ValueDependent = true; - if (initExprs[I]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (initExprs[I]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - } - InitExprs.insert(C, InitExprs.end(), initExprs.begin(), initExprs.end()); + + setDependence(computeDependence(this)); } void InitListExpr::reserveInits(const ASTContext &C, unsigned NumInits) { @@ -2388,6 +2272,64 @@ Stmt *BlockExpr::getBody() { // Generic Expression Routines //===----------------------------------------------------------------------===// +bool Expr::isReadIfDiscardedInCPlusPlus11() const { + // In C++11, discarded-value expressions of a certain form are special, + // according to [expr]p10: + // The lvalue-to-rvalue conversion (4.1) is applied only if the + // expression is an lvalue of volatile-qualified type and it has + // one of the following forms: + if (!isGLValue() || !getType().isVolatileQualified()) + return false; + + const Expr *E = IgnoreParens(); + + // - id-expression (5.1.1), + if (isa<DeclRefExpr>(E)) + return true; + + // - subscripting (5.2.1), + if (isa<ArraySubscriptExpr>(E)) + return true; + + // - class member access (5.2.5), + if (isa<MemberExpr>(E)) + return true; + + // - indirection (5.3.1), + if (auto *UO = dyn_cast<UnaryOperator>(E)) + if (UO->getOpcode() == UO_Deref) + return true; + + if (auto *BO = dyn_cast<BinaryOperator>(E)) { + // - pointer-to-member operation (5.5), + if (BO->isPtrMemOp()) + return true; + + // - comma expression (5.18) where the right operand is one of the above. + if (BO->getOpcode() == BO_Comma) + return BO->getRHS()->isReadIfDiscardedInCPlusPlus11(); + } + + // - conditional expression (5.16) where both the second and the third + // operands are one of the above, or + if (auto *CO = dyn_cast<ConditionalOperator>(E)) + return CO->getTrueExpr()->isReadIfDiscardedInCPlusPlus11() && + CO->getFalseExpr()->isReadIfDiscardedInCPlusPlus11(); + // The related edge case of "*x ?: *x". + if (auto *BCO = + dyn_cast<BinaryConditionalOperator>(E)) { + if (auto *OVE = dyn_cast<OpaqueValueExpr>(BCO->getTrueExpr())) + return OVE->getSourceExpr()->isReadIfDiscardedInCPlusPlus11() && + BCO->getFalseExpr()->isReadIfDiscardedInCPlusPlus11(); + } + + // Objective-C++ extensions to the rule. + if (isa<PseudoObjectExpr>(E) || isa<ObjCIvarRefExpr>(E)) + return true; + + return false; +} + /// isUnusedResultAWarning - Return true if this immediate expression should /// be warned about if the result is unused. If so, fill in Loc and Ranges /// with location to warn on and the source range[s] to report with the @@ -2576,6 +2518,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, // If we don't know precisely what we're looking at, let's not warn. case UnresolvedLookupExprClass: case CXXUnresolvedConstructExprClass: + case RecoveryExprClass: return false; case CXXTemporaryObjectExprClass: @@ -2675,20 +2618,31 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, } case CXXFunctionalCastExprClass: case CStyleCastExprClass: { - // Ignore an explicit cast to void unless the operand is a non-trivial - // volatile lvalue. + // Ignore an explicit cast to void, except in C++98 if the operand is a + // volatile glvalue for which we would trigger an implicit read in any + // other language mode. (Such an implicit read always happens as part of + // the lvalue conversion in C, and happens in C++ for expressions of all + // forms where it seems likely the user intended to trigger a volatile + // load.) const CastExpr *CE = cast<CastExpr>(this); + const Expr *SubE = CE->getSubExpr()->IgnoreParens(); if (CE->getCastKind() == CK_ToVoid) { - if (CE->getSubExpr()->isGLValue() && - CE->getSubExpr()->getType().isVolatileQualified()) { - const DeclRefExpr *DRE = - dyn_cast<DeclRefExpr>(CE->getSubExpr()->IgnoreParens()); - if (!(DRE && isa<VarDecl>(DRE->getDecl()) && - cast<VarDecl>(DRE->getDecl())->hasLocalStorage()) && - !isa<CallExpr>(CE->getSubExpr()->IgnoreParens())) { - return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, - R1, R2, Ctx); - } + if (Ctx.getLangOpts().CPlusPlus && !Ctx.getLangOpts().CPlusPlus11 && + SubE->isReadIfDiscardedInCPlusPlus11()) { + // Suppress the "unused value" warning for idiomatic usage of + // '(void)var;' used to suppress "unused variable" warnings. + if (auto *DRE = dyn_cast<DeclRefExpr>(SubE)) + if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) + if (!VD->isExternallyVisible()) + return false; + + // The lvalue-to-rvalue conversion would have no effect for an array. + // It's implausible that the programmer expected this to result in a + // volatile array load, so don't warn. + if (SubE->getType()->isArrayType()) + return false; + + return SubE->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); } return false; } @@ -2900,6 +2854,12 @@ static Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { return IgnoreImplicitSingleStep(E); } +static Expr *IgnoreParensOnlySingleStep(Expr *E) { + if (auto *PE = dyn_cast<ParenExpr>(E)) + return PE->getSubExpr(); + return E; +} + static Expr *IgnoreParensSingleStep(Expr *E) { if (auto *PE = dyn_cast<ParenExpr>(E)) return PE->getSubExpr(); @@ -2919,9 +2879,6 @@ static Expr *IgnoreParensSingleStep(Expr *E) { return CE->getChosenSubExpr(); } - else if (auto *CE = dyn_cast<ConstantExpr>(E)) - return CE->getSubExpr(); - return E; } @@ -3026,12 +2983,16 @@ Expr *Expr::IgnoreUnlessSpelledInSource() { Expr *LastE = nullptr; while (E != LastE) { LastE = E; - E = E->IgnoreParenImpCasts(); + E = IgnoreExprNodes(E, IgnoreImplicitSingleStep, + IgnoreImpCastsExtraSingleStep, + IgnoreParensOnlySingleStep); auto SR = E->getSourceRange(); if (auto *C = dyn_cast<CXXConstructExpr>(E)) { - if (C->getNumArgs() == 1) { + auto NumArgs = C->getNumArgs(); + if (NumArgs == 1 || + (NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) { Expr *A = C->getArg(0); if (A->getSourceRange() == SR || !isa<CXXTemporaryObjectExpr>(C)) E = A; @@ -3039,7 +3000,18 @@ Expr *Expr::IgnoreUnlessSpelledInSource() { } if (auto *C = dyn_cast<CXXMemberCallExpr>(E)) { - Expr *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts(); + Expr *ExprNode = C->getImplicitObjectArgument(); + if (ExprNode->getSourceRange() == SR) { + E = ExprNode; + continue; + } + if (auto *PE = dyn_cast<ParenExpr>(ExprNode)) { + if (PE->getSourceRange() == C->getSourceRange()) { + E = PE; + continue; + } + } + ExprNode = ExprNode->IgnoreParenImpCasts(); if (ExprNode->getSourceRange() == SR) E = ExprNode; } @@ -3206,6 +3178,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, switch (getStmtClass()) { default: break; + case Stmt::ExprWithCleanupsClass: + return cast<ExprWithCleanups>(this)->getSubExpr()->isConstantInitializer( + Ctx, IsForRef, Culprit); case StringLiteralClass: case ObjCEncodeExprClass: return true; @@ -3319,6 +3294,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, case ObjCBridgedCastExprClass: case CXXDynamicCastExprClass: case CXXReinterpretCastExprClass: + case CXXAddrspaceCastExprClass: case CXXConstCastExprClass: { const CastExpr *CE = cast<CastExpr>(this); @@ -3385,6 +3361,26 @@ namespace { bool hasSideEffects() const { return HasSideEffects; } + void VisitDecl(const Decl *D) { + if (!D) + return; + + // We assume the caller checks subexpressions (eg, the initializer, VLA + // bounds) for side-effects on our behalf. + if (auto *VD = dyn_cast<VarDecl>(D)) { + // Registering a destructor is a side-effect. + if (IncludePossibleEffects && VD->isThisDeclarationADefinition() && + VD->needsDestruction(Context)) + HasSideEffects = true; + } + } + + void VisitDeclStmt(const DeclStmt *DS) { + for (auto *D : DS->decls()) + VisitDecl(D); + Inherited::VisitDeclStmt(DS); + } + void VisitExpr(const Expr *E) { if (!HasSideEffects && E->HasSideEffects(Context, IncludePossibleEffects)) @@ -3421,6 +3417,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case SubstNonTypeTemplateParmPackExprClass: case FunctionParmPackExprClass: case TypoExprClass: + case RecoveryExprClass: case CXXFoldExprClass: llvm_unreachable("shouldn't see dependent / unresolved nodes here"); @@ -3457,6 +3454,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case OpaqueValueExprClass: case SourceLocExprClass: case ConceptSpecializationExprClass: + case RequiresExprClass: // These never have a side-effect. return false; @@ -3515,7 +3513,10 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case ParenExprClass: case ArraySubscriptExprClass: + case MatrixSubscriptExprClass: case OMPArraySectionExprClass: + case OMPArrayShapingExprClass: + case OMPIteratorExprClass: case MemberExprClass: case ConditionalOperatorClass: case BinaryConditionalOperatorClass: @@ -3586,6 +3587,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case CXXStaticCastExprClass: case CXXReinterpretCastExprClass: case CXXConstCastExprClass: + case CXXAddrspaceCastExprClass: case CXXFunctionalCastExprClass: case BuiltinBitCastExprClass: { // While volatile reads are side-effecting in both C and C++, we treat them @@ -3627,7 +3629,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case LambdaExprClass: { const LambdaExpr *LE = cast<LambdaExpr>(this); for (Expr *E : LE->capture_inits()) - if (E->HasSideEffects(Ctx, IncludePossibleEffects)) + if (E && E->HasSideEffects(Ctx, IncludePossibleEffects)) return true; return false; } @@ -3810,6 +3812,11 @@ Expr::isNullPointerConstant(ASTContext &Ctx, return Source->isNullPointerConstant(Ctx, NPC); } + // If the expression has no type information, it cannot be a null pointer + // constant. + if (getType().isNull()) + return NPCK_NotNull; + // C++11 nullptr_t is always a null pointer constant. if (getType()->isNullPtrType()) return NPCK_CXX11_nullptr; @@ -4148,28 +4155,16 @@ void ExtVectorElementExpr::getEncodedElementAccess( } } -ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, +ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr *> args, QualType Type, SourceLocation BLoc, SourceLocation RP) - : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary, - Type->isDependentType(), Type->isDependentType(), - Type->isInstantiationDependentType(), - Type->containsUnexpandedParameterPack()), - BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size()) -{ + : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary), + BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size()) { SubExprs = new (C) Stmt*[args.size()]; - for (unsigned i = 0; i != args.size(); i++) { - if (args[i]->isTypeDependent()) - ExprBits.TypeDependent = true; - if (args[i]->isValueDependent()) - ExprBits.ValueDependent = true; - if (args[i]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (args[i]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - + for (unsigned i = 0; i != args.size(); i++) SubExprs[i] = args[i]; - } + + setDependence(computeDependence(this)); } void ShuffleVectorExpr::setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs) { @@ -4187,11 +4182,7 @@ GenericSelectionExpr::GenericSelectionExpr( bool ContainsUnexpandedParameterPack, unsigned ResultIndex) : Expr(GenericSelectionExprClass, AssocExprs[ResultIndex]->getType(), AssocExprs[ResultIndex]->getValueKind(), - AssocExprs[ResultIndex]->getObjectKind(), - AssocExprs[ResultIndex]->isTypeDependent(), - AssocExprs[ResultIndex]->isValueDependent(), - AssocExprs[ResultIndex]->isInstantiationDependent(), - ContainsUnexpandedParameterPack), + AssocExprs[ResultIndex]->getObjectKind()), NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { assert(AssocTypes.size() == AssocExprs.size() && @@ -4205,6 +4196,8 @@ GenericSelectionExpr::GenericSelectionExpr( getTrailingObjects<Stmt *>() + AssocExprStartIndex); std::copy(AssocTypes.begin(), AssocTypes.end(), getTrailingObjects<TypeSourceInfo *>()); + + setDependence(computeDependence(this, ContainsUnexpandedParameterPack)); } GenericSelectionExpr::GenericSelectionExpr( @@ -4213,10 +4206,7 @@ GenericSelectionExpr::GenericSelectionExpr( SourceLocation DefaultLoc, SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack) : Expr(GenericSelectionExprClass, Context.DependentTy, VK_RValue, - OK_Ordinary, - /*isTypeDependent=*/true, - /*isValueDependent=*/true, - /*isInstantiationDependent=*/true, ContainsUnexpandedParameterPack), + OK_Ordinary), NumAssocs(AssocExprs.size()), ResultIndex(ResultDependentIndex), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { assert(AssocTypes.size() == AssocExprs.size() && @@ -4229,6 +4219,8 @@ GenericSelectionExpr::GenericSelectionExpr( getTrailingObjects<Stmt *>() + AssocExprStartIndex); std::copy(AssocTypes.begin(), AssocTypes.end(), getTrailingObjects<TypeSourceInfo *>()); + + setDependence(computeDependence(this, ContainsUnexpandedParameterPack)); } GenericSelectionExpr::GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs) @@ -4287,15 +4279,11 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, llvm::ArrayRef<Designator> Designators, SourceLocation EqualOrColonLoc, bool GNUSyntax, - ArrayRef<Expr*> IndexExprs, - Expr *Init) - : Expr(DesignatedInitExprClass, Ty, - Init->getValueKind(), Init->getObjectKind(), - Init->isTypeDependent(), Init->isValueDependent(), - Init->isInstantiationDependent(), - Init->containsUnexpandedParameterPack()), - EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax), - NumDesignators(Designators.size()), NumSubExprs(IndexExprs.size() + 1) { + ArrayRef<Expr *> IndexExprs, Expr *Init) + : Expr(DesignatedInitExprClass, Ty, Init->getValueKind(), + Init->getObjectKind()), + EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax), + NumDesignators(Designators.size()), NumSubExprs(IndexExprs.size() + 1) { this->Designators = new (C) Designator[NumDesignators]; // Record the initializer itself. @@ -4307,38 +4295,10 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, unsigned IndexIdx = 0; for (unsigned I = 0; I != NumDesignators; ++I) { this->Designators[I] = Designators[I]; - if (this->Designators[I].isArrayDesignator()) { - // Compute type- and value-dependence. - Expr *Index = IndexExprs[IndexIdx]; - if (Index->isTypeDependent() || Index->isValueDependent()) - ExprBits.TypeDependent = ExprBits.ValueDependent = true; - if (Index->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - // Propagate unexpanded parameter packs. - if (Index->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - // Copy the index expressions into permanent storage. *Child++ = IndexExprs[IndexIdx++]; } else if (this->Designators[I].isArrayRangeDesignator()) { - // Compute type- and value-dependence. - Expr *Start = IndexExprs[IndexIdx]; - Expr *End = IndexExprs[IndexIdx + 1]; - if (Start->isTypeDependent() || Start->isValueDependent() || - End->isTypeDependent() || End->isValueDependent()) { - ExprBits.TypeDependent = ExprBits.ValueDependent = true; - ExprBits.InstantiationDependent = true; - } else if (Start->isInstantiationDependent() || - End->isInstantiationDependent()) { - ExprBits.InstantiationDependent = true; - } - - // Propagate unexpanded parameter packs. - if (Start->containsUnexpandedParameterPack() || - End->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - // Copy the start/end expressions into permanent storage. *Child++ = IndexExprs[IndexIdx++]; *Child++ = IndexExprs[IndexIdx++]; @@ -4346,6 +4306,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, } assert(IndexIdx == IndexExprs.size() && "Wrong number of index expressions"); + setDependence(computeDependence(this)); } DesignatedInitExpr * @@ -4449,14 +4410,19 @@ void DesignatedInitExpr::ExpandDesignator(const ASTContext &C, unsigned Idx, } DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C, - SourceLocation lBraceLoc, Expr *baseExpr, SourceLocation rBraceLoc) - : Expr(DesignatedInitUpdateExprClass, baseExpr->getType(), VK_RValue, - OK_Ordinary, false, false, false, false) { + SourceLocation lBraceLoc, + Expr *baseExpr, + SourceLocation rBraceLoc) + : Expr(DesignatedInitUpdateExprClass, baseExpr->getType(), VK_RValue, + OK_Ordinary) { BaseAndUpdaterExprs[0] = baseExpr; InitListExpr *ILE = new (C) InitListExpr(C, lBraceLoc, None, rBraceLoc); ILE->setType(baseExpr->getType()); BaseAndUpdaterExprs[1] = ILE; + + // FIXME: this is wrong, set it correctly. + setDependence(ExprDependence::None); } SourceLocation DesignatedInitUpdateExpr::getBeginLoc() const { @@ -4469,23 +4435,13 @@ SourceLocation DesignatedInitUpdateExpr::getEndLoc() const { ParenListExpr::ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs, SourceLocation RParenLoc) - : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, - false, false), + : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary), LParenLoc(LParenLoc), RParenLoc(RParenLoc) { ParenListExprBits.NumExprs = Exprs.size(); - for (unsigned I = 0, N = Exprs.size(); I != N; ++I) { - if (Exprs[I]->isTypeDependent()) - ExprBits.TypeDependent = true; - if (Exprs[I]->isValueDependent()) - ExprBits.ValueDependent = true; - if (Exprs[I]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (Exprs[I]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - + for (unsigned I = 0, N = Exprs.size(); I != N; ++I) getTrailingObjects<Stmt *>()[I] = Exprs[I]; - } + setDependence(computeDependence(this)); } ParenListExpr::ParenListExpr(EmptyShell Empty, unsigned NumExprs) @@ -4509,6 +4465,115 @@ ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx, return new (Mem) ParenListExpr(EmptyShell(), NumExprs); } +BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, + Opcode opc, QualType ResTy, ExprValueKind VK, + ExprObjectKind OK, SourceLocation opLoc, + FPOptionsOverride FPFeatures) + : Expr(BinaryOperatorClass, ResTy, VK, OK) { + BinaryOperatorBits.Opc = opc; + assert(!isCompoundAssignmentOp() && + "Use CompoundAssignOperator for compound assignments"); + BinaryOperatorBits.OpLoc = opLoc; + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); + if (BinaryOperatorBits.HasFPFeatures) + *getTrailingFPFeatures() = FPFeatures; + setDependence(computeDependence(this)); +} + +BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, + Opcode opc, QualType ResTy, ExprValueKind VK, + ExprObjectKind OK, SourceLocation opLoc, + FPOptionsOverride FPFeatures, bool dead2) + : Expr(CompoundAssignOperatorClass, ResTy, VK, OK) { + BinaryOperatorBits.Opc = opc; + assert(isCompoundAssignmentOp() && + "Use CompoundAssignOperator for compound assignments"); + BinaryOperatorBits.OpLoc = opLoc; + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); + if (BinaryOperatorBits.HasFPFeatures) + *getTrailingFPFeatures() = FPFeatures; + setDependence(computeDependence(this)); +} + +BinaryOperator *BinaryOperator::CreateEmpty(const ASTContext &C, + bool HasFPFeatures) { + unsigned Extra = sizeOfTrailingObjects(HasFPFeatures); + void *Mem = + C.Allocate(sizeof(BinaryOperator) + Extra, alignof(BinaryOperator)); + return new (Mem) BinaryOperator(EmptyShell()); +} + +BinaryOperator *BinaryOperator::Create(const ASTContext &C, Expr *lhs, + Expr *rhs, Opcode opc, QualType ResTy, + ExprValueKind VK, ExprObjectKind OK, + SourceLocation opLoc, + FPOptionsOverride FPFeatures) { + bool HasFPFeatures = FPFeatures.requiresTrailingStorage(); + unsigned Extra = sizeOfTrailingObjects(HasFPFeatures); + void *Mem = + C.Allocate(sizeof(BinaryOperator) + Extra, alignof(BinaryOperator)); + return new (Mem) + BinaryOperator(C, lhs, rhs, opc, ResTy, VK, OK, opLoc, FPFeatures); +} + +CompoundAssignOperator * +CompoundAssignOperator::CreateEmpty(const ASTContext &C, bool HasFPFeatures) { + unsigned Extra = sizeOfTrailingObjects(HasFPFeatures); + void *Mem = C.Allocate(sizeof(CompoundAssignOperator) + Extra, + alignof(CompoundAssignOperator)); + return new (Mem) CompoundAssignOperator(C, EmptyShell(), HasFPFeatures); +} + +CompoundAssignOperator * +CompoundAssignOperator::Create(const ASTContext &C, Expr *lhs, Expr *rhs, + Opcode opc, QualType ResTy, ExprValueKind VK, + ExprObjectKind OK, SourceLocation opLoc, + FPOptionsOverride FPFeatures, + QualType CompLHSType, QualType CompResultType) { + bool HasFPFeatures = FPFeatures.requiresTrailingStorage(); + unsigned Extra = sizeOfTrailingObjects(HasFPFeatures); + void *Mem = C.Allocate(sizeof(CompoundAssignOperator) + Extra, + alignof(CompoundAssignOperator)); + return new (Mem) + CompoundAssignOperator(C, lhs, rhs, opc, ResTy, VK, OK, opLoc, FPFeatures, + CompLHSType, CompResultType); +} + +UnaryOperator *UnaryOperator::CreateEmpty(const ASTContext &C, + bool hasFPFeatures) { + void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(hasFPFeatures), + alignof(UnaryOperator)); + return new (Mem) UnaryOperator(hasFPFeatures, EmptyShell()); +} + +UnaryOperator::UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc, + QualType type, ExprValueKind VK, ExprObjectKind OK, + SourceLocation l, bool CanOverflow, + FPOptionsOverride FPFeatures) + : Expr(UnaryOperatorClass, type, VK, OK), Val(input) { + UnaryOperatorBits.Opc = opc; + UnaryOperatorBits.CanOverflow = CanOverflow; + UnaryOperatorBits.Loc = l; + UnaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); + setDependence(computeDependence(this)); +} + +UnaryOperator *UnaryOperator::Create(const ASTContext &C, Expr *input, + Opcode opc, QualType type, + ExprValueKind VK, ExprObjectKind OK, + SourceLocation l, bool CanOverflow, + FPOptionsOverride FPFeatures) { + bool HasFPFeatures = FPFeatures.requiresTrailingStorage(); + unsigned Size = totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures); + void *Mem = C.Allocate(Size, alignof(UnaryOperator)); + return new (Mem) + UnaryOperator(C, input, opc, type, VK, OK, l, CanOverflow, FPFeatures); +} + const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e)) e = ewc->getSubExpr(); @@ -4559,10 +4624,9 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax, } PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK, - Expr *syntax, ArrayRef<Expr*> semantics, + Expr *syntax, ArrayRef<Expr *> semantics, unsigned resultIndex) - : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary, - /*filled in at end of ctor*/ false, false, false, false) { + : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary) { PseudoObjectExprBits.NumSubExprs = semantics.size() + 1; PseudoObjectExprBits.ResultIndex = resultIndex + 1; @@ -4570,20 +4634,13 @@ PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK, Expr *E = (i == 0 ? syntax : semantics[i-1]); getSubExprsBuffer()[i] = E; - if (E->isTypeDependent()) - ExprBits.TypeDependent = true; - if (E->isValueDependent()) - ExprBits.ValueDependent = true; - if (E->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (E->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - if (isa<OpaqueValueExpr>(E)) assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != nullptr && "opaque-value semantic expressions for pseudo-object " "operations must have sources"); } + + setDependence(computeDependence(this)); } //===----------------------------------------------------------------------===// @@ -4610,25 +4667,14 @@ Stmt::const_child_range UnaryExprOrTypeTraitExpr::children() const { return const_child_range(&Argument.Ex, &Argument.Ex + 1); } -AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, - QualType t, AtomicOp op, SourceLocation RP) - : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary, - false, false, false, false), - NumSubExprs(args.size()), BuiltinLoc(BLoc), RParenLoc(RP), Op(op) -{ +AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr *> args, QualType t, + AtomicOp op, SourceLocation RP) + : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary), + NumSubExprs(args.size()), BuiltinLoc(BLoc), RParenLoc(RP), Op(op) { assert(args.size() == getNumSubExprs(op) && "wrong number of subexpressions"); - for (unsigned i = 0; i != args.size(); i++) { - if (args[i]->isTypeDependent()) - ExprBits.TypeDependent = true; - if (args[i]->isValueDependent()) - ExprBits.ValueDependent = true; - if (args[i]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (args[i]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - + for (unsigned i = 0; i != args.size(); i++) SubExprs[i] = args[i]; - } + setDependence(computeDependence(this)); } unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { @@ -4730,3 +4776,211 @@ QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) { } return OriginalTy; } + +RecoveryExpr::RecoveryExpr(ASTContext &Ctx, QualType T, SourceLocation BeginLoc, + SourceLocation EndLoc, ArrayRef<Expr *> SubExprs) + : Expr(RecoveryExprClass, T.getNonReferenceType(), + T->isDependentType() ? VK_LValue : getValueKindForType(T), + OK_Ordinary), + BeginLoc(BeginLoc), EndLoc(EndLoc), NumExprs(SubExprs.size()) { + assert(!T.isNull()); + assert(llvm::all_of(SubExprs, [](Expr* E) { return E != nullptr; })); + + llvm::copy(SubExprs, getTrailingObjects<Expr *>()); + setDependence(computeDependence(this)); +} + +RecoveryExpr *RecoveryExpr::Create(ASTContext &Ctx, QualType T, + SourceLocation BeginLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> SubExprs) { + void *Mem = Ctx.Allocate(totalSizeToAlloc<Expr *>(SubExprs.size()), + alignof(RecoveryExpr)); + return new (Mem) RecoveryExpr(Ctx, T, BeginLoc, EndLoc, SubExprs); +} + +RecoveryExpr *RecoveryExpr::CreateEmpty(ASTContext &Ctx, unsigned NumSubExprs) { + void *Mem = Ctx.Allocate(totalSizeToAlloc<Expr *>(NumSubExprs), + alignof(RecoveryExpr)); + return new (Mem) RecoveryExpr(EmptyShell(), NumSubExprs); +} + +void OMPArrayShapingExpr::setDimensions(ArrayRef<Expr *> Dims) { + assert( + NumDims == Dims.size() && + "Preallocated number of dimensions is different from the provided one."); + llvm::copy(Dims, getTrailingObjects<Expr *>()); +} + +void OMPArrayShapingExpr::setBracketsRanges(ArrayRef<SourceRange> BR) { + assert( + NumDims == BR.size() && + "Preallocated number of dimensions is different from the provided one."); + llvm::copy(BR, getTrailingObjects<SourceRange>()); +} + +OMPArrayShapingExpr::OMPArrayShapingExpr(QualType ExprTy, Expr *Op, + SourceLocation L, SourceLocation R, + ArrayRef<Expr *> Dims) + : Expr(OMPArrayShapingExprClass, ExprTy, VK_LValue, OK_Ordinary), LPLoc(L), + RPLoc(R), NumDims(Dims.size()) { + setBase(Op); + setDimensions(Dims); + setDependence(computeDependence(this)); +} + +OMPArrayShapingExpr * +OMPArrayShapingExpr::Create(const ASTContext &Context, QualType T, Expr *Op, + SourceLocation L, SourceLocation R, + ArrayRef<Expr *> Dims, + ArrayRef<SourceRange> BracketRanges) { + assert(Dims.size() == BracketRanges.size() && + "Different number of dimensions and brackets ranges."); + void *Mem = Context.Allocate( + totalSizeToAlloc<Expr *, SourceRange>(Dims.size() + 1, Dims.size()), + alignof(OMPArrayShapingExpr)); + auto *E = new (Mem) OMPArrayShapingExpr(T, Op, L, R, Dims); + E->setBracketsRanges(BracketRanges); + return E; +} + +OMPArrayShapingExpr *OMPArrayShapingExpr::CreateEmpty(const ASTContext &Context, + unsigned NumDims) { + void *Mem = Context.Allocate( + totalSizeToAlloc<Expr *, SourceRange>(NumDims + 1, NumDims), + alignof(OMPArrayShapingExpr)); + return new (Mem) OMPArrayShapingExpr(EmptyShell(), NumDims); +} + +void OMPIteratorExpr::setIteratorDeclaration(unsigned I, Decl *D) { + assert(I < NumIterators && + "Idx is greater or equal the number of iterators definitions."); + getTrailingObjects<Decl *>()[I] = D; +} + +void OMPIteratorExpr::setAssignmentLoc(unsigned I, SourceLocation Loc) { + assert(I < NumIterators && + "Idx is greater or equal the number of iterators definitions."); + getTrailingObjects< + SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) + + static_cast<int>(RangeLocOffset::AssignLoc)] = Loc; +} + +void OMPIteratorExpr::setIteratorRange(unsigned I, Expr *Begin, + SourceLocation ColonLoc, Expr *End, + SourceLocation SecondColonLoc, + Expr *Step) { + assert(I < NumIterators && + "Idx is greater or equal the number of iterators definitions."); + getTrailingObjects<Expr *>()[I * static_cast<int>(RangeExprOffset::Total) + + static_cast<int>(RangeExprOffset::Begin)] = + Begin; + getTrailingObjects<Expr *>()[I * static_cast<int>(RangeExprOffset::Total) + + static_cast<int>(RangeExprOffset::End)] = End; + getTrailingObjects<Expr *>()[I * static_cast<int>(RangeExprOffset::Total) + + static_cast<int>(RangeExprOffset::Step)] = Step; + getTrailingObjects< + SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) + + static_cast<int>(RangeLocOffset::FirstColonLoc)] = + ColonLoc; + getTrailingObjects< + SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) + + static_cast<int>(RangeLocOffset::SecondColonLoc)] = + SecondColonLoc; +} + +Decl *OMPIteratorExpr::getIteratorDecl(unsigned I) { + return getTrailingObjects<Decl *>()[I]; +} + +OMPIteratorExpr::IteratorRange OMPIteratorExpr::getIteratorRange(unsigned I) { + IteratorRange Res; + Res.Begin = + getTrailingObjects<Expr *>()[I * static_cast<int>( + RangeExprOffset::Total) + + static_cast<int>(RangeExprOffset::Begin)]; + Res.End = + getTrailingObjects<Expr *>()[I * static_cast<int>( + RangeExprOffset::Total) + + static_cast<int>(RangeExprOffset::End)]; + Res.Step = + getTrailingObjects<Expr *>()[I * static_cast<int>( + RangeExprOffset::Total) + + static_cast<int>(RangeExprOffset::Step)]; + return Res; +} + +SourceLocation OMPIteratorExpr::getAssignLoc(unsigned I) const { + return getTrailingObjects< + SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) + + static_cast<int>(RangeLocOffset::AssignLoc)]; +} + +SourceLocation OMPIteratorExpr::getColonLoc(unsigned I) const { + return getTrailingObjects< + SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) + + static_cast<int>(RangeLocOffset::FirstColonLoc)]; +} + +SourceLocation OMPIteratorExpr::getSecondColonLoc(unsigned I) const { + return getTrailingObjects< + SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) + + static_cast<int>(RangeLocOffset::SecondColonLoc)]; +} + +void OMPIteratorExpr::setHelper(unsigned I, const OMPIteratorHelperData &D) { + getTrailingObjects<OMPIteratorHelperData>()[I] = D; +} + +OMPIteratorHelperData &OMPIteratorExpr::getHelper(unsigned I) { + return getTrailingObjects<OMPIteratorHelperData>()[I]; +} + +const OMPIteratorHelperData &OMPIteratorExpr::getHelper(unsigned I) const { + return getTrailingObjects<OMPIteratorHelperData>()[I]; +} + +OMPIteratorExpr::OMPIteratorExpr( + QualType ExprTy, SourceLocation IteratorKwLoc, SourceLocation L, + SourceLocation R, ArrayRef<OMPIteratorExpr::IteratorDefinition> Data, + ArrayRef<OMPIteratorHelperData> Helpers) + : Expr(OMPIteratorExprClass, ExprTy, VK_LValue, OK_Ordinary), + IteratorKwLoc(IteratorKwLoc), LPLoc(L), RPLoc(R), + NumIterators(Data.size()) { + for (unsigned I = 0, E = Data.size(); I < E; ++I) { + const IteratorDefinition &D = Data[I]; + setIteratorDeclaration(I, D.IteratorDecl); + setAssignmentLoc(I, D.AssignmentLoc); + setIteratorRange(I, D.Range.Begin, D.ColonLoc, D.Range.End, + D.SecondColonLoc, D.Range.Step); + setHelper(I, Helpers[I]); + } + setDependence(computeDependence(this)); +} + +OMPIteratorExpr * +OMPIteratorExpr::Create(const ASTContext &Context, QualType T, + SourceLocation IteratorKwLoc, SourceLocation L, + SourceLocation R, + ArrayRef<OMPIteratorExpr::IteratorDefinition> Data, + ArrayRef<OMPIteratorHelperData> Helpers) { + assert(Data.size() == Helpers.size() && + "Data and helpers must have the same size."); + void *Mem = Context.Allocate( + totalSizeToAlloc<Decl *, Expr *, SourceLocation, OMPIteratorHelperData>( + Data.size(), Data.size() * static_cast<int>(RangeExprOffset::Total), + Data.size() * static_cast<int>(RangeLocOffset::Total), + Helpers.size()), + alignof(OMPIteratorExpr)); + return new (Mem) OMPIteratorExpr(T, IteratorKwLoc, L, R, Data, Helpers); +} + +OMPIteratorExpr *OMPIteratorExpr::CreateEmpty(const ASTContext &Context, + unsigned NumIterators) { + void *Mem = Context.Allocate( + totalSizeToAlloc<Decl *, Expr *, SourceLocation, OMPIteratorHelperData>( + NumIterators, NumIterators * static_cast<int>(RangeExprOffset::Total), + NumIterators * static_cast<int>(RangeLocOffset::Total), NumIterators), + alignof(OMPIteratorExpr)); + return new (Mem) OMPIteratorExpr(EmptyShell(), NumIterators); +} |