diff options
Diffstat (limited to 'include/clang/AST/Expr.h')
| -rw-r--r-- | include/clang/AST/Expr.h | 1308 |
1 files changed, 761 insertions, 547 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index c18fbf05df68..3de73428829b 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -32,6 +32,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/TrailingObjects.h" namespace clang { class APValue; @@ -99,10 +100,9 @@ struct SubobjectAdjustment { } }; -/// Expr - This represents one expression. Note that Expr's are subclasses of -/// Stmt. This allows an expression to be transparently used any place a Stmt -/// is required. -/// +/// This represents one expression. Note that Expr's are subclasses of Stmt. +/// This allows an expression to be transparently used any place a Stmt is +/// required. class Expr : public Stmt { QualType TR; @@ -583,7 +583,8 @@ public: /// this function returns true, it returns the folded constant in Result. If /// the expression is a glvalue, an lvalue-to-rvalue conversion will be /// applied. - bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const; + bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, + bool InConstantContext = false) const; /// EvaluateAsBooleanCondition - Return true if this is a constant /// which we can fold and convert to a boolean condition using @@ -600,7 +601,7 @@ public: /// EvaluateAsInt - Return true if this is a constant which we can fold and /// convert to an integer, using any crazy technique that we want to. - bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, + bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; /// EvaluateAsFloat - Return true if this is a constant which we can fold and @@ -632,8 +633,13 @@ public: /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded /// integer. This must be called on an expression that constant folds to an /// integer. - llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, - SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const; + llvm::APSInt EvaluateKnownConstInt( + const ASTContext &Ctx, + SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const; + + llvm::APSInt EvaluateKnownConstIntCheckOverflow( + const ASTContext &Ctx, + SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const; void EvaluateForOverflow(const ASTContext &Ctx) const; @@ -864,6 +870,70 @@ public: }; //===----------------------------------------------------------------------===// +// Wrapper Expressions. +//===----------------------------------------------------------------------===// + +/// FullExpr - Represents a "full-expression" node. +class FullExpr : public Expr { +protected: + Stmt *SubExpr; + + FullExpr(StmtClass SC, Expr *subexpr) + : Expr(SC, subexpr->getType(), + subexpr->getValueKind(), subexpr->getObjectKind(), + subexpr->isTypeDependent(), subexpr->isValueDependent(), + subexpr->isInstantiationDependent(), + subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr) {} + FullExpr(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty) {} +public: + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + Expr *getSubExpr() { return cast<Expr>(SubExpr); } + + /// As with any mutator of the AST, be very careful when modifying an + /// existing AST to preserve its invariants. + void setSubExpr(Expr *E) { SubExpr = E; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() >= firstFullExprConstant && + T->getStmtClass() <= lastFullExprConstant; + } +}; + +/// ConstantExpr - An expression that occurs in a constant context. +class ConstantExpr : public FullExpr { + ConstantExpr(Expr *subexpr) + : FullExpr(ConstantExprClass, subexpr) {} + +public: + static ConstantExpr *Create(const ASTContext &Context, Expr *E) { + assert(!isa<ConstantExpr>(E)); + return new (Context) ConstantExpr(E); + } + + /// Build an empty constant expression wrapper. + explicit ConstantExpr(EmptyShell Empty) + : FullExpr(ConstantExprClass, Empty) {} + + SourceLocation getBeginLoc() const LLVM_READONLY { + return SubExpr->getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY { + return SubExpr->getEndLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConstantExprClass; + } + + // Iterators + child_range children() { return child_range(&SubExpr, &SubExpr+1); } + const_child_range children() const { + return const_child_range(&SubExpr, &SubExpr + 1); + } +}; + +//===----------------------------------------------------------------------===// // Primary Expressions. //===----------------------------------------------------------------------===// @@ -875,7 +945,6 @@ public: class OpaqueValueExpr : public Expr { friend class ASTStmtReader; Expr *SourceExpr; - SourceLocation Loc; public: OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, @@ -889,8 +958,9 @@ public: T->isInstantiationDependentType() || (SourceExpr && SourceExpr->isInstantiationDependent()), false), - SourceExpr(SourceExpr), Loc(Loc) { + SourceExpr(SourceExpr) { setIsUnique(false); + OpaqueValueExprBits.Loc = Loc; } /// Given an expression which invokes a copy constructor --- i.e. a @@ -899,20 +969,19 @@ public: static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr); explicit OpaqueValueExpr(EmptyShell Empty) - : Expr(OpaqueValueExprClass, Empty) { } + : Expr(OpaqueValueExprClass, Empty) {} /// Retrieve the location of this expression. - SourceLocation getLocation() const { return Loc; } + SourceLocation getLocation() const { return OpaqueValueExprBits.Loc; } - SourceLocation getLocStart() const LLVM_READONLY { - return SourceExpr ? SourceExpr->getLocStart() : Loc; + SourceLocation getBeginLoc() const LLVM_READONLY { + return SourceExpr ? SourceExpr->getBeginLoc() : getLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return SourceExpr ? SourceExpr->getLocEnd() : Loc; + SourceLocation getEndLoc() const LLVM_READONLY { + return SourceExpr ? SourceExpr->getEndLoc() : getLocation(); } SourceLocation getExprLoc() const LLVM_READONLY { - if (SourceExpr) return SourceExpr->getExprLoc(); - return Loc; + return SourceExpr ? SourceExpr->getExprLoc() : getLocation(); } child_range children() { @@ -974,63 +1043,52 @@ class DeclRefExpr final private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc, NamedDecl *, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// The declaration that we are referencing. ValueDecl *D; - /// The location of the declaration name itself. - SourceLocation Loc; - /// Provides source/type location info for the declaration name /// embedded in D. DeclarationNameLoc DNLoc; size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const { - return hasQualifier() ? 1 : 0; + return hasQualifier(); } size_t numTrailingObjects(OverloadToken<NamedDecl *>) const { - return hasFoundDecl() ? 1 : 0; + return hasFoundDecl(); } size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return hasTemplateKWAndArgsInfo() ? 1 : 0; + return hasTemplateKWAndArgsInfo(); } /// Test whether there is a distinct FoundDecl attached to the end of /// this DRE. bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; } - DeclRefExpr(const ASTContext &Ctx, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - ValueDecl *D, bool RefersToEnlosingVariableOrCapture, - const DeclarationNameInfo &NameInfo, - NamedDecl *FoundD, - const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK); + DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool RefersToEnlosingVariableOrCapture, + const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, + const TemplateArgumentListInfo *TemplateArgs, QualType T, + ExprValueKind VK); /// Construct an empty declaration reference expression. - explicit DeclRefExpr(EmptyShell Empty) - : Expr(DeclRefExprClass, Empty) { } + explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) {} /// Computes the type- and value-dependence flags for this /// declaration reference expression. - void computeDependence(const ASTContext &C); + void computeDependence(const ASTContext &Ctx); public: - DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T, + DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, + bool RefersToEnclosingVariableOrCapture, QualType T, ExprValueKind VK, SourceLocation L, - const DeclarationNameLoc &LocInfo = DeclarationNameLoc()) - : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), - D(D), Loc(L), DNLoc(LocInfo) { - DeclRefExprBits.HasQualifier = 0; - DeclRefExprBits.HasTemplateKWAndArgsInfo = 0; - DeclRefExprBits.HasFoundDecl = 0; - DeclRefExprBits.HadMultipleCandidates = 0; - DeclRefExprBits.RefersToEnclosingVariableOrCapture = - RefersToEnclosingVariableOrCapture; - computeDependence(D->getASTContext()); - } + const DeclarationNameLoc &LocInfo = DeclarationNameLoc()); static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, @@ -1048,8 +1106,7 @@ public: const TemplateArgumentListInfo *TemplateArgs = nullptr); /// Construct an empty declaration reference expression. - static DeclRefExpr *CreateEmpty(const ASTContext &Context, - bool HasQualifier, + static DeclRefExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier, bool HasFoundDecl, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); @@ -1059,13 +1116,13 @@ public: void setDecl(ValueDecl *NewD) { D = NewD; } DeclarationNameInfo getNameInfo() const { - return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc); + return DeclarationNameInfo(getDecl()->getDeclName(), getLocation(), DNLoc); } - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; + SourceLocation getLocation() const { return DeclRefExprBits.Loc; } + void setLocation(SourceLocation L) { DeclRefExprBits.Loc = L; } + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; /// Determine whether this declaration reference was preceded by a /// C++ nested-name-specifier, e.g., \c N::foo. @@ -1108,21 +1165,24 @@ public: /// Retrieve the location of the template keyword preceding /// this name, if any. SourceLocation getTemplateKeywordLoc() const { - if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { - if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { - if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } @@ -1147,7 +1207,6 @@ public: const TemplateArgumentLoc *getTemplateArgs() const { if (!hasExplicitTemplateArgs()) return nullptr; - return getTrailingObjects<TemplateArgumentLoc>(); } @@ -1156,7 +1215,6 @@ public: unsigned getNumTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; } @@ -1194,68 +1252,6 @@ public: const_child_range children() const { return const_child_range(const_child_iterator(), const_child_iterator()); } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// [C99 6.4.2.2] - A predefined identifier such as __func__. -class PredefinedExpr : public Expr { -public: - enum IdentType { - Func, - Function, - LFunction, // Same as Function, but as wide string. - FuncDName, - FuncSig, - LFuncSig, // Same as FuncSig, but as as wide string - PrettyFunction, - /// The same as PrettyFunction, except that the - /// 'virtual' keyword is omitted for virtual member functions. - PrettyFunctionNoVirtual - }; - -private: - SourceLocation Loc; - IdentType Type; - Stmt *FnName; - -public: - PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, - StringLiteral *SL); - - /// Construct an empty predefined expression. - explicit PredefinedExpr(EmptyShell Empty) - : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {} - - IdentType getIdentType() const { return Type; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - StringLiteral *getFunctionName(); - const StringLiteral *getFunctionName() const { - return const_cast<PredefinedExpr *>(this)->getFunctionName(); - } - - static StringRef getIdentTypeName(IdentType IT); - static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == PredefinedExprClass; - } - - // Iterators - child_range children() { return child_range(&FnName, &FnName + 1); } - const_child_range children() const { - return const_child_range(&FnName, &FnName + 1); - } - - friend class ASTStmtReader; }; /// Used by IntegerLiteral/FloatingLiteral to store the numeric without @@ -1331,8 +1327,8 @@ public: /// Returns a new empty integer literal. static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty); - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } /// Retrieve the location of the literal. SourceLocation getLocation() const { return Loc; } @@ -1370,8 +1366,8 @@ class FixedPointLiteral : public Expr, public APIntStorage { QualType type, SourceLocation l, unsigned Scale); - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } /// \brief Retrieve the location of the literal. SourceLocation getLocation() const { return Loc; } @@ -1424,8 +1420,8 @@ public: return static_cast<CharacterKind>(CharacterLiteralBits.Kind); } - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } unsigned getValue() const { return Value; } @@ -1497,8 +1493,8 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } static bool classof(const Stmt *T) { return T->getStmtClass() == FloatingLiteralClass; @@ -1534,8 +1530,10 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - SourceLocation getLocStart() const LLVM_READONLY { return Val->getLocStart(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Val->getLocEnd(); } + SourceLocation getBeginLoc() const LLVM_READONLY { + return Val->getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY { return Val->getEndLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ImaginaryLiteralClass; @@ -1549,14 +1547,15 @@ public: }; /// StringLiteral - This represents a string literal expression, e.g. "foo" -/// or L"bar" (wide strings). The actual string is returned by getBytes() -/// is NOT null-terminated, and the length of the string is determined by -/// calling getByteLength(). The C type for a string is always a -/// ConstantArrayType. In C++, the char type is const qualified, in C it is -/// not. +/// or L"bar" (wide strings). The actual string data can be obtained with +/// getBytes() and is NOT null-terminated. The length of the string data is +/// determined by calling getByteLength(). +/// +/// The C type for a string is always a ConstantArrayType. In C++, the char +/// type is const qualified, in C it is not. /// /// Note that strings in C can be formed by concatenation of multiple string -/// literal pptokens in translation phase #6. This keeps track of the locations +/// literal pptokens in translation phase #6. This keeps track of the locations /// of each of these pieces. /// /// Strings in C can also be truncated and extended by assigning into arrays, @@ -1564,131 +1563,156 @@ public: /// char X[2] = "foobar"; /// In this case, getByteLength() will return 6, but the string literal will /// have type "char[2]". -class StringLiteral : public Expr { +class StringLiteral final + : public Expr, + private llvm::TrailingObjects<StringLiteral, unsigned, SourceLocation, + char> { + friend class ASTStmtReader; + friend TrailingObjects; + + /// StringLiteral is followed by several trailing objects. They are in order: + /// + /// * A single unsigned storing the length in characters of this string. The + /// length in bytes is this length times the width of a single character. + /// Always present and stored as a trailing objects because storing it in + /// StringLiteral would increase the size of StringLiteral by sizeof(void *) + /// due to alignment requirements. If you add some data to StringLiteral, + /// consider moving it inside StringLiteral. + /// + /// * An array of getNumConcatenated() SourceLocation, one for each of the + /// token this string is made of. + /// + /// * An array of getByteLength() char used to store the string data. + public: - enum StringKind { - Ascii, - Wide, - UTF8, - UTF16, - UTF32 - }; + enum StringKind { Ascii, Wide, UTF8, UTF16, UTF32 }; private: - friend class ASTStmtReader; + unsigned numTrailingObjects(OverloadToken<unsigned>) const { return 1; } + unsigned numTrailingObjects(OverloadToken<SourceLocation>) const { + return getNumConcatenated(); + } - union { - const char *asChar; - const uint16_t *asUInt16; - const uint32_t *asUInt32; - } StrData; - unsigned Length; - unsigned CharByteWidth : 4; - unsigned Kind : 3; - unsigned IsPascal : 1; - unsigned NumConcatenated; - SourceLocation TokLocs[1]; + unsigned numTrailingObjects(OverloadToken<char>) const { + return getByteLength(); + } + + char *getStrDataAsChar() { return getTrailingObjects<char>(); } + const char *getStrDataAsChar() const { return getTrailingObjects<char>(); } - StringLiteral(QualType Ty) : - Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false, - false) {} + const uint16_t *getStrDataAsUInt16() const { + return reinterpret_cast<const uint16_t *>(getTrailingObjects<char>()); + } + + const uint32_t *getStrDataAsUInt32() const { + return reinterpret_cast<const uint32_t *>(getTrailingObjects<char>()); + } + + /// Build a string literal. + StringLiteral(const ASTContext &Ctx, StringRef Str, StringKind Kind, + bool Pascal, QualType Ty, const SourceLocation *Loc, + unsigned NumConcatenated); + + /// Build an empty string literal. + StringLiteral(EmptyShell Empty, unsigned NumConcatenated, unsigned Length, + unsigned CharByteWidth); - static int mapCharByteWidth(TargetInfo const &target,StringKind k); + /// Map a target and string kind to the appropriate character width. + static unsigned mapCharByteWidth(TargetInfo const &Target, StringKind SK); + + /// Set one of the string literal token. + void setStrTokenLoc(unsigned TokNum, SourceLocation L) { + assert(TokNum < getNumConcatenated() && "Invalid tok number"); + getTrailingObjects<SourceLocation>()[TokNum] = L; + } public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. - static StringLiteral *Create(const ASTContext &C, StringRef Str, + static StringLiteral *Create(const ASTContext &Ctx, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, - const SourceLocation *Loc, unsigned NumStrs); + const SourceLocation *Loc, + unsigned NumConcatenated); /// Simple constructor for string literals made from one token. - static StringLiteral *Create(const ASTContext &C, StringRef Str, + static StringLiteral *Create(const ASTContext &Ctx, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, SourceLocation Loc) { - return Create(C, Str, Kind, Pascal, Ty, &Loc, 1); + return Create(Ctx, Str, Kind, Pascal, Ty, &Loc, 1); } /// Construct an empty string literal. - static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs); + static StringLiteral *CreateEmpty(const ASTContext &Ctx, + unsigned NumConcatenated, unsigned Length, + unsigned CharByteWidth); StringRef getString() const { - assert(CharByteWidth==1 - && "This function is used in places that assume strings use char"); - return StringRef(StrData.asChar, getByteLength()); + assert(getCharByteWidth() == 1 && + "This function is used in places that assume strings use char"); + return StringRef(getStrDataAsChar(), getByteLength()); } /// Allow access to clients that need the byte representation, such as /// ASTWriterStmt::VisitStringLiteral(). StringRef getBytes() const { // FIXME: StringRef may not be the right type to use as a result for this. - if (CharByteWidth == 1) - return StringRef(StrData.asChar, getByteLength()); - if (CharByteWidth == 4) - return StringRef(reinterpret_cast<const char*>(StrData.asUInt32), - getByteLength()); - assert(CharByteWidth == 2 && "unsupported CharByteWidth"); - return StringRef(reinterpret_cast<const char*>(StrData.asUInt16), - getByteLength()); + return StringRef(getStrDataAsChar(), getByteLength()); } void outputString(raw_ostream &OS) const; uint32_t getCodeUnit(size_t i) const { - assert(i < Length && "out of bounds access"); - if (CharByteWidth == 1) - return static_cast<unsigned char>(StrData.asChar[i]); - if (CharByteWidth == 4) - return StrData.asUInt32[i]; - assert(CharByteWidth == 2 && "unsupported CharByteWidth"); - return StrData.asUInt16[i]; + assert(i < getLength() && "out of bounds access"); + switch (getCharByteWidth()) { + case 1: + return static_cast<unsigned char>(getStrDataAsChar()[i]); + case 2: + return getStrDataAsUInt16()[i]; + case 4: + return getStrDataAsUInt32()[i]; + } + llvm_unreachable("Unsupported character width!"); } - unsigned getByteLength() const { return CharByteWidth*Length; } - unsigned getLength() const { return Length; } - unsigned getCharByteWidth() const { return CharByteWidth; } - - /// Sets the string data to the given string data. - void setString(const ASTContext &C, StringRef Str, - StringKind Kind, bool IsPascal); - - StringKind getKind() const { return static_cast<StringKind>(Kind); } + unsigned getByteLength() const { return getCharByteWidth() * getLength(); } + unsigned getLength() const { return *getTrailingObjects<unsigned>(); } + unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; } + StringKind getKind() const { + return static_cast<StringKind>(StringLiteralBits.Kind); + } - bool isAscii() const { return Kind == Ascii; } - bool isWide() const { return Kind == Wide; } - bool isUTF8() const { return Kind == UTF8; } - bool isUTF16() const { return Kind == UTF16; } - bool isUTF32() const { return Kind == UTF32; } - bool isPascal() const { return IsPascal; } + bool isAscii() const { return getKind() == Ascii; } + bool isWide() const { return getKind() == Wide; } + bool isUTF8() const { return getKind() == UTF8; } + bool isUTF16() const { return getKind() == UTF16; } + bool isUTF32() const { return getKind() == UTF32; } + bool isPascal() const { return StringLiteralBits.IsPascal; } bool containsNonAscii() const { - StringRef Str = getString(); - for (unsigned i = 0, e = Str.size(); i != e; ++i) - if (!isASCII(Str[i])) + for (auto c : getString()) + if (!isASCII(c)) return true; return false; } bool containsNonAsciiOrNull() const { - StringRef Str = getString(); - for (unsigned i = 0, e = Str.size(); i != e; ++i) - if (!isASCII(Str[i]) || !Str[i]) + for (auto c : getString()) + if (!isASCII(c) || !c) return true; return false; } /// getNumConcatenated - Get the number of string literal tokens that were /// concatenated in translation phase #6 to form this string literal. - unsigned getNumConcatenated() const { return NumConcatenated; } + unsigned getNumConcatenated() const { + return StringLiteralBits.NumConcatenated; + } + /// Get one of the string literal token. SourceLocation getStrTokenLoc(unsigned TokNum) const { - assert(TokNum < NumConcatenated && "Invalid tok number"); - return TokLocs[TokNum]; - } - void setStrTokenLoc(unsigned TokNum, SourceLocation L) { - assert(TokNum < NumConcatenated && "Invalid tok number"); - TokLocs[TokNum] = L; + assert(TokNum < getNumConcatenated() && "Invalid tok number"); + return getTrailingObjects<SourceLocation>()[TokNum]; } /// getLocationOfByte - Return a source location that points to the specified @@ -1705,14 +1729,18 @@ public: unsigned *StartTokenByteOffset = nullptr) const; typedef const SourceLocation *tokloc_iterator; - tokloc_iterator tokloc_begin() const { return TokLocs; } - tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; } - SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; } - SourceLocation getLocEnd() const LLVM_READONLY { - return TokLocs[NumConcatenated - 1]; + tokloc_iterator tokloc_begin() const { + return getTrailingObjects<SourceLocation>(); } + tokloc_iterator tokloc_end() const { + return getTrailingObjects<SourceLocation>() + getNumConcatenated(); + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return *tokloc_begin(); } + SourceLocation getEndLoc() const LLVM_READONLY { return *(tokloc_end() - 1); } + static bool classof(const Stmt *T) { return T->getStmtClass() == StringLiteralClass; } @@ -1726,6 +1754,91 @@ public: } }; +/// [C99 6.4.2.2] - A predefined identifier such as __func__. +class PredefinedExpr final + : public Expr, + private llvm::TrailingObjects<PredefinedExpr, Stmt *> { + friend class ASTStmtReader; + friend TrailingObjects; + + // PredefinedExpr is optionally followed by a single trailing + // "Stmt *" for the predefined identifier. It is present if and only if + // hasFunctionName() is true and is always a "StringLiteral *". + +public: + enum IdentKind { + Func, + Function, + LFunction, // Same as Function, but as wide string. + FuncDName, + FuncSig, + LFuncSig, // Same as FuncSig, but as as wide string + PrettyFunction, + /// The same as PrettyFunction, except that the + /// 'virtual' keyword is omitted for virtual member functions. + PrettyFunctionNoVirtual + }; + +private: + PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, + StringLiteral *SL); + + explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName); + + /// True if this PredefinedExpr has storage for a function name. + bool hasFunctionName() const { return PredefinedExprBits.HasFunctionName; } + + void setFunctionName(StringLiteral *SL) { + assert(hasFunctionName() && + "This PredefinedExpr has no storage for a function name!"); + *getTrailingObjects<Stmt *>() = SL; + } + +public: + /// Create a PredefinedExpr. + static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L, + QualType FNTy, IdentKind IK, StringLiteral *SL); + + /// Create an empty PredefinedExpr. + static PredefinedExpr *CreateEmpty(const ASTContext &Ctx, + bool HasFunctionName); + + IdentKind getIdentKind() const { + return static_cast<IdentKind>(PredefinedExprBits.Kind); + } + + SourceLocation getLocation() const { return PredefinedExprBits.Loc; } + void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; } + + StringLiteral *getFunctionName() { + return hasFunctionName() + ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>()) + : nullptr; + } + + const StringLiteral *getFunctionName() const { + return hasFunctionName() + ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>()) + : nullptr; + } + + static StringRef getIdentKindName(IdentKind IK); + static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl); + + SourceLocation getBeginLoc() const { return getLocation(); } + SourceLocation getEndLoc() const { return getLocation(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == PredefinedExprClass; + } + + // Iterators + child_range children() { + return child_range(getTrailingObjects<Stmt *>(), + getTrailingObjects<Stmt *>() + hasFunctionName()); + } +}; + /// ParenExpr - This represents a parethesized expression, e.g. "(1)". This /// AST node is only formed if full location information is requested. class ParenExpr : public Expr { @@ -1748,8 +1861,8 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - SourceLocation getLocStart() const LLVM_READONLY { return L; } - SourceLocation getLocEnd() const LLVM_READONLY { return R; } + SourceLocation getBeginLoc() const LLVM_READONLY { return L; } + SourceLocation getEndLoc() const LLVM_READONLY { return R; } /// Get the location of the left parentheses '('. SourceLocation getLParen() const { return L; } @@ -1781,15 +1894,11 @@ public: /// later returns zero in the type of the operand. /// class UnaryOperator : public Expr { + Stmt *Val; + public: typedef UnaryOperatorKind Opcode; -private: - unsigned Opc : 5; - unsigned CanOverflow : 1; - SourceLocation Loc; - Stmt *Val; -public: UnaryOperator(Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow) : Expr(UnaryOperatorClass, type, VK, OK, @@ -1798,21 +1907,28 @@ public: (input->isInstantiationDependent() || type->isInstantiationDependentType()), input->containsUnexpandedParameterPack()), - Opc(opc), CanOverflow(CanOverflow), Loc(l), Val(input) {} + Val(input) { + UnaryOperatorBits.Opc = opc; + UnaryOperatorBits.CanOverflow = CanOverflow; + UnaryOperatorBits.Loc = l; + } /// Build an empty unary operator. - explicit UnaryOperator(EmptyShell Empty) - : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { } + explicit UnaryOperator(EmptyShell Empty) : Expr(UnaryOperatorClass, Empty) { + UnaryOperatorBits.Opc = UO_AddrOf; + } - Opcode getOpcode() const { return static_cast<Opcode>(Opc); } - void setOpcode(Opcode O) { Opc = O; } + Opcode getOpcode() const { + return static_cast<Opcode>(UnaryOperatorBits.Opc); + } + void setOpcode(Opcode Opc) { UnaryOperatorBits.Opc = Opc; } Expr *getSubExpr() const { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } /// getOperatorLoc - Return the location of the operator. - SourceLocation getOperatorLoc() const { return Loc; } - void setOperatorLoc(SourceLocation L) { Loc = L; } + SourceLocation getOperatorLoc() const { return UnaryOperatorBits.Loc; } + void setOperatorLoc(SourceLocation L) { UnaryOperatorBits.Loc = L; } /// Returns true if the unary operator can cause an overflow. For instance, /// signed int i = INT_MAX; i++; @@ -1820,8 +1936,8 @@ public: /// Due to integer promotions, c++ is promoted to an int before the postfix /// increment, and the result is an int that cannot overflow. However, i++ /// can overflow. - bool canOverflow() const { return CanOverflow; } - void setCanOverflow(bool C) { CanOverflow = C; } + bool canOverflow() const { return UnaryOperatorBits.CanOverflow; } + void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; } /// isPostfix - Return true if this is a postfix operation, like x++. static bool isPostfix(Opcode Op) { @@ -1872,13 +1988,13 @@ public: /// the given unary opcode. static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); - SourceLocation getLocStart() const LLVM_READONLY { - return isPostfix() ? Val->getLocStart() : Loc; + SourceLocation getBeginLoc() const LLVM_READONLY { + return isPostfix() ? Val->getBeginLoc() : getOperatorLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return isPostfix() ? Loc : Val->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return isPostfix() ? getOperatorLoc() : Val->getEndLoc(); } - SourceLocation getExprLoc() const LLVM_READONLY { return Loc; } + SourceLocation getExprLoc() const { return getOperatorLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryOperatorClass; @@ -1980,8 +2096,8 @@ public: /// contains the location of the period (if there is one) and the /// identifier. SourceRange getSourceRange() const LLVM_READONLY { return Range; } - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } + SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } }; /// OffsetOfExpr - [C99 7.17] - This represents an expression of the form @@ -2080,8 +2196,8 @@ public: return NumExprs; } - SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == OffsetOfExprClass; @@ -2176,8 +2292,8 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return OpLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return OpLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryExprOrTypeTraitExprClass; @@ -2194,9 +2310,11 @@ public: /// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. class ArraySubscriptExpr : public Expr { - enum { LHS, RHS, END_EXPR=2 }; - Stmt* SubExprs[END_EXPR]; - SourceLocation RBracketLoc; + enum { LHS, RHS, END_EXPR }; + Stmt *SubExprs[END_EXPR]; + + bool lhsIsBase() const { return getRHS()->getType()->isIntegerType(); } + public: ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, ExprValueKind VK, ExprObjectKind OK, @@ -2207,10 +2325,10 @@ public: (lhs->isInstantiationDependent() || rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())), - RBracketLoc(rbracketloc) { + rhs->containsUnexpandedParameterPack())) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; + ArraySubscriptExprBits.RBracketLoc = rbracketloc; } /// Create an empty array subscript expression. @@ -2234,29 +2352,23 @@ public: const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } - Expr *getBase() { - return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS(); - } + Expr *getBase() { return lhsIsBase() ? getLHS() : getRHS(); } + const Expr *getBase() const { return lhsIsBase() ? getLHS() : getRHS(); } - const Expr *getBase() const { - return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS(); - } + Expr *getIdx() { return lhsIsBase() ? getRHS() : getLHS(); } + const Expr *getIdx() const { return lhsIsBase() ? getRHS() : getLHS(); } - Expr *getIdx() { - return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getLHS()->getBeginLoc(); } + SourceLocation getEndLoc() const { return getRBracketLoc(); } - const Expr *getIdx() const { - return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS(); + SourceLocation getRBracketLoc() const { + return ArraySubscriptExprBits.RBracketLoc; } - - SourceLocation getLocStart() const LLVM_READONLY { - return getLHS()->getLocStart(); + void setRBracketLoc(SourceLocation L) { + ArraySubscriptExprBits.RBracketLoc = L; } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } - - SourceLocation getRBracketLoc() const { return RBracketLoc; } - void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } SourceLocation getExprLoc() const LLVM_READONLY { return getBase()->getExprLoc(); @@ -2282,127 +2394,221 @@ public: /// a subclass for overloaded operator calls that use operator syntax, e.g., /// "str1 + str2" to resolve to a function call. class CallExpr : public Expr { - enum { FN=0, PREARGS_START=1 }; - Stmt **SubExprs; + enum { FN = 0, PREARGS_START = 1 }; + + /// The number of arguments in the call expression. unsigned NumArgs; + + /// The location of the right parenthese. This has a different meaning for + /// the derived classes of CallExpr. SourceLocation RParenLoc; void updateDependenciesFromArg(Expr *Arg); + // CallExpr store some data in trailing objects. However since CallExpr + // is used a base of other expression classes we cannot use + // llvm::TrailingObjects. Instead we manually perform the pointer arithmetic + // and casts. + // + // The trailing objects are in order: + // + // * A single "Stmt *" for the callee expression. + // + // * An array of getNumPreArgs() "Stmt *" for the pre-argument expressions. + // + // * An array of getNumArgs() "Stmt *" for the argument expressions. + // + // Note that we store the offset in bytes from the this pointer to the start + // of the trailing objects. It would be perfectly possible to compute it + // based on the dynamic kind of the CallExpr. However 1.) we have plenty of + // space in the bit-fields of Stmt. 2.) It was benchmarked to be faster to + // compute this once and then load the offset from the bit-fields of Stmt, + // instead of re-computing the offset each time the trailing objects are + // accessed. + + /// Return a pointer to the start of the trailing array of "Stmt *". + Stmt **getTrailingStmts() { + return reinterpret_cast<Stmt **>(reinterpret_cast<char *>(this) + + CallExprBits.OffsetToTrailingObjects); + } + Stmt *const *getTrailingStmts() const { + return const_cast<CallExpr *>(this)->getTrailingStmts(); + } + + /// Map a statement class to the appropriate offset in bytes from the + /// this pointer to the trailing objects. + static unsigned offsetToTrailingObjects(StmtClass SC); + +public: + enum class ADLCallKind : bool { NotADL, UsesADL }; + static constexpr ADLCallKind NotADL = ADLCallKind::NotADL; + static constexpr ADLCallKind UsesADL = ADLCallKind::UsesADL; + protected: - // These versions of the constructor are for derived classes. - CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, - ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t, - ExprValueKind VK, SourceLocation rparenloc); - CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef<Expr *> args, - QualType t, ExprValueKind VK, SourceLocation rparenloc); - CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, + /// Build a call expression, assuming that appropriate storage has been + /// allocated for the trailing objects. + CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation RParenLoc, unsigned MinNumArgs, ADLCallKind UsesADL); + + /// Build an empty call expression, for deserialization. + CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, EmptyShell Empty); - Stmt *getPreArg(unsigned i) { - assert(i < getNumPreArgs() && "Prearg access out of range!"); - return SubExprs[PREARGS_START+i]; + /// Return the size in bytes needed for the trailing objects. + /// Used by the derived classes to allocate the right amount of storage. + static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs) { + return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *); } - const Stmt *getPreArg(unsigned i) const { - assert(i < getNumPreArgs() && "Prearg access out of range!"); - return SubExprs[PREARGS_START+i]; + + Stmt *getPreArg(unsigned I) { + assert(I < getNumPreArgs() && "Prearg access out of range!"); + return getTrailingStmts()[PREARGS_START + I]; + } + const Stmt *getPreArg(unsigned I) const { + assert(I < getNumPreArgs() && "Prearg access out of range!"); + return getTrailingStmts()[PREARGS_START + I]; } - void setPreArg(unsigned i, Stmt *PreArg) { - assert(i < getNumPreArgs() && "Prearg access out of range!"); - SubExprs[PREARGS_START+i] = PreArg; + void setPreArg(unsigned I, Stmt *PreArg) { + assert(I < getNumPreArgs() && "Prearg access out of range!"); + getTrailingStmts()[PREARGS_START + I] = PreArg; } unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } public: - CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t, - ExprValueKind VK, SourceLocation rparenloc); + /// Create a call expression. Fn is the callee expression, Args is the + /// argument array, Ty is the type of the call expression (which is *not* + /// the return type in general), VK is the value kind of the call expression + /// (lvalue, rvalue, ...), and RParenLoc is the location of the right + /// parenthese in the call expression. MinNumArgs specifies the minimum + /// number of arguments. The actual number of arguments will be the greater + /// of Args.size() and MinNumArgs. This is used in a few places to allocate + /// enough storage for the default arguments. UsesADL specifies whether the + /// callee was found through argument-dependent lookup. + /// + /// Note that you can use CreateTemporary if you need a temporary call + /// expression on the stack. + static CallExpr *Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation RParenLoc, unsigned MinNumArgs = 0, + ADLCallKind UsesADL = NotADL); - /// Build an empty call expression. - CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty); + /// Create a temporary call expression with no arguments in the memory + /// pointed to by Mem. Mem must points to at least sizeof(CallExpr) + /// + sizeof(Stmt *) bytes of storage, aligned to alignof(CallExpr): + /// + /// \code{.cpp} + /// llvm::AlignedCharArray<alignof(CallExpr), + /// sizeof(CallExpr) + sizeof(Stmt *)> Buffer; + /// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer.buffer, etc); + /// \endcode + static CallExpr *CreateTemporary(void *Mem, Expr *Fn, QualType Ty, + ExprValueKind VK, SourceLocation RParenLoc, + ADLCallKind UsesADL = NotADL); - const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); } - Expr *getCallee() { return cast<Expr>(SubExprs[FN]); } - void setCallee(Expr *F) { SubExprs[FN] = F; } + /// Create an empty call expression, for deserialization. + static CallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + EmptyShell Empty); + + Expr *getCallee() { return cast<Expr>(getTrailingStmts()[FN]); } + const Expr *getCallee() const { return cast<Expr>(getTrailingStmts()[FN]); } + void setCallee(Expr *F) { getTrailingStmts()[FN] = F; } + + ADLCallKind getADLCallKind() const { + return static_cast<ADLCallKind>(CallExprBits.UsesADL); + } + void setADLCallKind(ADLCallKind V = UsesADL) { + CallExprBits.UsesADL = static_cast<bool>(V); + } + bool usesADL() const { return getADLCallKind() == UsesADL; } - Decl *getCalleeDecl(); + Decl *getCalleeDecl() { return getCallee()->getReferencedDeclOfCallee(); } const Decl *getCalleeDecl() const { - return const_cast<CallExpr*>(this)->getCalleeDecl(); + return getCallee()->getReferencedDeclOfCallee(); } - /// If the callee is a FunctionDecl, return it. Otherwise return 0. - FunctionDecl *getDirectCallee(); + /// If the callee is a FunctionDecl, return it. Otherwise return null. + FunctionDecl *getDirectCallee() { + return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); + } const FunctionDecl *getDirectCallee() const { - return const_cast<CallExpr*>(this)->getDirectCallee(); + return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); } /// getNumArgs - Return the number of actual arguments to this call. - /// unsigned getNumArgs() const { return NumArgs; } /// Retrieve the call arguments. Expr **getArgs() { - return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START); + return reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START + + getNumPreArgs()); } const Expr *const *getArgs() const { - return reinterpret_cast<Expr **>(SubExprs + getNumPreArgs() + - PREARGS_START); + return reinterpret_cast<const Expr *const *>( + getTrailingStmts() + PREARGS_START + getNumPreArgs()); } /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); + assert(Arg < getNumArgs() && "Arg access out of range!"); + return getArgs()[Arg]; } const Expr *getArg(unsigned Arg) const { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); + assert(Arg < getNumArgs() && "Arg access out of range!"); + return getArgs()[Arg]; } /// setArg - Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { - assert(Arg < NumArgs && "Arg access out of range!"); - SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr; + assert(Arg < getNumArgs() && "Arg access out of range!"); + getArgs()[Arg] = ArgExpr; } - /// setNumArgs - This changes the number of arguments present in this call. - /// Any orphaned expressions are deleted by this, and any new operands are set - /// to null. - void setNumArgs(const ASTContext& C, unsigned NumArgs); + /// Reduce the number of arguments in this call expression. This is used for + /// example during error recovery to drop extra arguments. There is no way + /// to perform the opposite because: 1.) We don't track how much storage + /// we have for the argument array 2.) This would potentially require growing + /// the argument array, something we cannot support since the arguments are + /// stored in a trailing array. + void shrinkNumArgs(unsigned NewNumArgs) { + assert((NewNumArgs <= getNumArgs()) && + "shrinkNumArgs cannot increase the number of arguments!"); + NumArgs = NewNumArgs; + } typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; typedef llvm::iterator_range<arg_iterator> arg_range; - typedef llvm::iterator_range<const_arg_iterator> arg_const_range; + typedef llvm::iterator_range<const_arg_iterator> const_arg_range; arg_range arguments() { return arg_range(arg_begin(), arg_end()); } - arg_const_range arguments() const { - return arg_const_range(arg_begin(), arg_end()); + const_arg_range arguments() const { + return const_arg_range(arg_begin(), arg_end()); } - arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); } - arg_iterator arg_end() { - return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); + arg_iterator arg_begin() { + return getTrailingStmts() + PREARGS_START + getNumPreArgs(); } + arg_iterator arg_end() { return arg_begin() + getNumArgs(); } + const_arg_iterator arg_begin() const { - return SubExprs+PREARGS_START+getNumPreArgs(); - } - const_arg_iterator arg_end() const { - return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); + return getTrailingStmts() + PREARGS_START + getNumPreArgs(); } + const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); } /// This method provides fast access to all the subexpressions of /// a CallExpr without going through the slower virtual child_iterator /// interface. This provides efficient reverse iteration of the /// subexpressions. This is currently used for CFG construction. - ArrayRef<Stmt*> getRawSubExprs() { - return llvm::makeArrayRef(SubExprs, - getNumPreArgs() + PREARGS_START + getNumArgs()); + ArrayRef<Stmt *> getRawSubExprs() { + return llvm::makeArrayRef(getTrailingStmts(), + PREARGS_START + getNumPreArgs() + getNumArgs()); } /// getNumCommas - Return the number of commas that must have been present in /// this function call. - unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } + unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; } /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID /// of the callee. If not, return 0. @@ -2417,18 +2623,27 @@ public: /// type. QualType getCallReturnType(const ASTContext &Ctx) const; + /// Returns the WarnUnusedResultAttr that is either declared on the called + /// function, or its return type declaration. + const Attr *getUnusedResultAttr(const ASTContext &Ctx) const; + + /// Returns true if this call expression should warn on unused results. + bool hasUnusedResultAttr(const ASTContext &Ctx) const { + return getUnusedResultAttr(Ctx) != nullptr; + } + SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; /// Return true if this is a call to __assume() or __builtin_assume() with /// a non-value-dependent constant parameter evaluating as false. bool isBuiltinAssumeFalse(const ASTContext &Ctx) const; bool isCallToStdMove() const { - const FunctionDecl* FD = getDirectCallee(); + const FunctionDecl *FD = getDirectCallee(); return getNumArgs() == 1 && FD && FD->isInStdNamespace() && FD->getIdentifier() && FD->getIdentifier()->isStr("move"); } @@ -2440,13 +2655,14 @@ public: // Iterators child_range children() { - return child_range(&SubExprs[0], - &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START); + return child_range(getTrailingStmts(), getTrailingStmts() + PREARGS_START + + getNumPreArgs() + getNumArgs()); } const_child_range children() const { - return const_child_range(&SubExprs[0], &SubExprs[0] + NumArgs + - getNumPreArgs() + PREARGS_START); + return const_child_range(getTrailingStmts(), + getTrailingStmts() + PREARGS_START + + getNumPreArgs() + getNumArgs()); } }; @@ -2468,6 +2684,10 @@ class MemberExpr final private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + friend class ASTReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// Base - the expression for the base pointer or structure references. In /// X.F, this is "X". Stmt *Base; @@ -2483,35 +2703,20 @@ class MemberExpr final /// MemberLoc - This is the location of the member name. SourceLocation MemberLoc; - /// This is the location of the -> or . in the expression. - SourceLocation OperatorLoc; - - /// IsArrow - True if this is "X->F", false if this is "X.F". - bool IsArrow : 1; - - /// True if this member expression used a nested-name-specifier to - /// refer to the member, e.g., "x->Base::f", or found its member via a using - /// declaration. When true, a MemberExprNameQualifier - /// structure is allocated immediately after the MemberExpr. - bool HasQualifierOrFoundDecl : 1; - - /// True if this member expression specified a template keyword - /// and/or a template argument list explicitly, e.g., x->f<int>, - /// x->template f, x->template f<int>. - /// When true, an ASTTemplateKWAndArgsInfo structure and its - /// TemplateArguments (if any) are present. - bool HasTemplateKWAndArgsInfo : 1; - - /// True if this member expression refers to a method that - /// was resolved from an overloaded set having size greater than 1. - bool HadMultipleCandidates : 1; - size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const { - return HasQualifierOrFoundDecl ? 1 : 0; + return hasQualifierOrFoundDecl(); } size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; + return hasTemplateKWAndArgsInfo(); + } + + bool hasQualifierOrFoundDecl() const { + return MemberExprBits.HasQualifierOrFoundDecl; + } + + bool hasTemplateKWAndArgsInfo() const { + return MemberExprBits.HasTemplateKWAndArgsInfo; } public: @@ -2522,10 +2727,13 @@ public: base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()), - MemberLoc(NameInfo.getLoc()), OperatorLoc(operatorloc), - IsArrow(isarrow), HasQualifierOrFoundDecl(false), - HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) { + MemberLoc(NameInfo.getLoc()) { assert(memberdecl->getDeclName() == NameInfo.getName()); + MemberExprBits.IsArrow = isarrow; + MemberExprBits.HasQualifierOrFoundDecl = false; + MemberExprBits.HasTemplateKWAndArgsInfo = false; + MemberExprBits.HadMultipleCandidates = false; + MemberExprBits.OperatorLoc = operatorloc; } // NOTE: this constructor should be used only when it is known that @@ -2538,10 +2746,13 @@ public: : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), - Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l), - OperatorLoc(operatorloc), IsArrow(isarrow), - HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), - HadMultipleCandidates(false) {} + Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l) { + MemberExprBits.IsArrow = isarrow; + MemberExprBits.HasQualifierOrFoundDecl = false; + MemberExprBits.HasTemplateKWAndArgsInfo = false; + MemberExprBits.HadMultipleCandidates = false; + MemberExprBits.OperatorLoc = operatorloc; + } static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc, @@ -2564,7 +2775,7 @@ public: /// Retrieves the declaration found by lookup. DeclAccessPair getFoundDecl() const { - if (!HasQualifierOrFoundDecl) + if (!hasQualifierOrFoundDecl()) return DeclAccessPair::make(getMemberDecl(), getMemberDecl()->getAccess()); return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl; @@ -2579,9 +2790,8 @@ public: /// nested-name-specifier that precedes the member name, with source-location /// information. NestedNameSpecifierLoc getQualifierLoc() const { - if (!HasQualifierOrFoundDecl) + if (!hasQualifierOrFoundDecl()) return NestedNameSpecifierLoc(); - return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc; } @@ -2595,21 +2805,24 @@ public: /// Retrieve the location of the template keyword preceding /// the member name, if any. SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the member name, if any. SourceLocation getLAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the member name, if any. SourceLocation getRAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } @@ -2656,18 +2869,18 @@ public: MemberLoc, MemberDNLoc); } - SourceLocation getOperatorLoc() const LLVM_READONLY { return OperatorLoc; } + SourceLocation getOperatorLoc() const { return MemberExprBits.OperatorLoc; } - bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } + bool isArrow() const { return MemberExprBits.IsArrow; } + void setArrow(bool A) { MemberExprBits.IsArrow = A; } /// getMemberLoc - Return the location of the "member", in X->F, it is the /// location of 'F'. SourceLocation getMemberLoc() const { return MemberLoc; } void setMemberLoc(SourceLocation L) { MemberLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; } @@ -2679,13 +2892,13 @@ public: /// Returns true if this member expression refers to a method that /// was resolved from an overloaded set having size greater than 1. bool hadMultipleCandidates() const { - return HadMultipleCandidates; + return MemberExprBits.HadMultipleCandidates; } /// Sets the flag telling whether this expression refers to /// a method that was resolved from an overloaded set having size /// greater than 1. void setHadMultipleCandidates(bool V = true) { - HadMultipleCandidates = V; + MemberExprBits.HadMultipleCandidates = V; } /// Returns true if virtual dispatch is performed. @@ -2705,10 +2918,6 @@ public: const_child_range children() const { return const_child_range(&Base, &Base + 1); } - - friend TrailingObjects; - friend class ASTReader; - friend class ASTStmtWriter; }; /// CompoundLiteralExpr - [C99 6.5.2.5] @@ -2756,19 +2965,19 @@ public: TInfoAndScope.setPointer(tinfo); } - SourceLocation getLocStart() const LLVM_READONLY { + SourceLocation getBeginLoc() const LLVM_READONLY { // FIXME: Init should never be null. if (!Init) return SourceLocation(); if (LParenLoc.isInvalid()) - return Init->getLocStart(); + return Init->getBeginLoc(); return LParenLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { + SourceLocation getEndLoc() const LLVM_READONLY { // FIXME: Init should never be null. if (!Init) return SourceLocation(); - return Init->getLocEnd(); + return Init->getEndLoc(); } static bool classof(const Stmt *T) { @@ -2787,28 +2996,15 @@ public: /// representation in the source code (ExplicitCastExpr's derived /// classes). class CastExpr : public Expr { -public: - using BasePathSizeTy = unsigned int; - static_assert(std::numeric_limits<BasePathSizeTy>::max() >= 16384, - "[implimits] Direct and indirect base classes [16384]."); - -private: Stmt *Op; bool CastConsistency() const; - BasePathSizeTy *BasePathSize(); - const CXXBaseSpecifier * const *path_buffer() const { return const_cast<CastExpr*>(this)->path_buffer(); } CXXBaseSpecifier **path_buffer(); - void setBasePathSize(BasePathSizeTy basePathSize) { - assert(!path_empty() && basePathSize != 0); - *(BasePathSize()) = basePathSize; - } - protected: CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, Expr *op, unsigned BasePathSize) @@ -2829,9 +3025,9 @@ protected: Op(op) { CastExprBits.Kind = kind; CastExprBits.PartOfExplicitCast = false; - CastExprBits.BasePathIsEmpty = BasePathSize == 0; - if (!path_empty()) - setBasePathSize(BasePathSize); + CastExprBits.BasePathSize = BasePathSize; + assert((CastExprBits.BasePathSize == BasePathSize) && + "BasePathSize overflow!"); assert(CastConsistency()); } @@ -2839,9 +3035,9 @@ protected: CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) : Expr(SC, Empty) { CastExprBits.PartOfExplicitCast = false; - CastExprBits.BasePathIsEmpty = BasePathSize == 0; - if (!path_empty()) - setBasePathSize(BasePathSize); + CastExprBits.BasePathSize = BasePathSize; + assert((CastExprBits.BasePathSize == BasePathSize) && + "BasePathSize overflow!"); } public: @@ -2868,13 +3064,9 @@ public: NamedDecl *getConversionFunction() const; typedef CXXBaseSpecifier **path_iterator; - typedef const CXXBaseSpecifier * const *path_const_iterator; - bool path_empty() const { return CastExprBits.BasePathIsEmpty; } - unsigned path_size() const { - if (path_empty()) - return 0U; - return *(const_cast<CastExpr *>(this)->BasePathSize()); - } + typedef const CXXBaseSpecifier *const *path_const_iterator; + bool path_empty() const { return path_size() == 0; } + unsigned path_size() const { return CastExprBits.BasePathSize; } path_iterator path_begin() { return path_buffer(); } path_iterator path_end() { return path_buffer() + path_size(); } path_const_iterator path_begin() const { return path_buffer(); } @@ -2922,17 +3114,11 @@ public: /// @endcode class ImplicitCastExpr final : public CastExpr, - private llvm::TrailingObjects<ImplicitCastExpr, CastExpr::BasePathSizeTy, - CXXBaseSpecifier *> { - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } + private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> { -private: ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, unsigned BasePathLength, ExprValueKind VK) - : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { - } + : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { } /// Construct an empty implicit cast. explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize) @@ -2958,11 +3144,11 @@ public: static ImplicitCastExpr *CreateEmpty(const ASTContext &Context, unsigned PathSize); - SourceLocation getLocStart() const LLVM_READONLY { - return getSubExpr()->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getSubExpr()->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return getSubExpr()->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return getSubExpr()->getEndLoc(); } static bool classof(const Stmt *T) { @@ -2975,8 +3161,13 @@ public: inline Expr *Expr::IgnoreImpCasts() { Expr *e = this; - while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) - e = ice->getSubExpr(); + while (true) + if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) + e = ice->getSubExpr(); + else if (FullExpr *fe = dyn_cast<FullExpr>(e)) + e = fe->getSubExpr(); + else + break; return e; } @@ -3032,8 +3223,7 @@ public: /// (Type)expr. For example: @c (int)f. class CStyleCastExpr final : public ExplicitCastExpr, - private llvm::TrailingObjects<CStyleCastExpr, CastExpr::BasePathSizeTy, - CXXBaseSpecifier *> { + private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> { SourceLocation LPLoc; // the location of the left paren SourceLocation RPLoc; // the location of the right paren @@ -3047,10 +3237,6 @@ class CStyleCastExpr final explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize) : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: static CStyleCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, @@ -3067,9 +3253,9 @@ public: SourceLocation getRParenLoc() const { return RPLoc; } void setRParenLoc(SourceLocation L) { RPLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return LPLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return getSubExpr()->getLocEnd(); + SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { + return getSubExpr()->getEndLoc(); } static bool classof(const Stmt *T) { @@ -3099,20 +3285,11 @@ public: /// "+" resolves to an overloaded operator, CXXOperatorCallExpr will /// be used to express the computation. class BinaryOperator : public Expr { -public: - typedef BinaryOperatorKind Opcode; - -private: - unsigned Opc : 6; - - // This is only meaningful for operations on floating point types and 0 - // otherwise. - unsigned FPFeatures : 2; - SourceLocation OpLoc; - enum { LHS, RHS, END_EXPR }; - Stmt* SubExprs[END_EXPR]; + Stmt *SubExprs[END_EXPR]; + public: + typedef BinaryOperatorKind Opcode; BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, @@ -3123,8 +3300,10 @@ public: (lhs->isInstantiationDependent() || rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())), - Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) { + rhs->containsUnexpandedParameterPack())) { + BinaryOperatorBits.Opc = opc; + BinaryOperatorBits.FPFeatures = FPFeatures.getInt(); + BinaryOperatorBits.OpLoc = opLoc; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; assert(!isCompoundAssignmentOp() && @@ -3132,26 +3311,29 @@ public: } /// Construct an empty binary operator. - explicit BinaryOperator(EmptyShell Empty) - : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { } + explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) { + BinaryOperatorBits.Opc = BO_Comma; + } - SourceLocation getExprLoc() const LLVM_READONLY { return OpLoc; } - SourceLocation getOperatorLoc() const { return OpLoc; } - void setOperatorLoc(SourceLocation L) { OpLoc = L; } + SourceLocation getExprLoc() const { return getOperatorLoc(); } + SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; } + void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; } - Opcode getOpcode() const { return static_cast<Opcode>(Opc); } - void setOpcode(Opcode O) { Opc = O; } + Opcode getOpcode() const { + return static_cast<Opcode>(BinaryOperatorBits.Opc); + } + void setOpcode(Opcode Opc) { BinaryOperatorBits.Opc = Opc; } Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } void setLHS(Expr *E) { SubExprs[LHS] = E; } Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } - SourceLocation getLocStart() const LLVM_READONLY { - return getLHS()->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getLHS()->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return getRHS()->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return getRHS()->getEndLoc(); } /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it @@ -3169,7 +3351,11 @@ public: static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); /// predicates to categorize the respective opcodes. - bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; } + static bool isPtrMemOp(Opcode Opc) { + return Opc == BO_PtrMemD || Opc == BO_PtrMemI; + } + bool isPtrMemOp() const { return isPtrMemOp(getOpcode()); } + static bool isMultiplicativeOp(Opcode Opc) { return Opc >= BO_Mul && Opc <= BO_Rem; } @@ -3268,16 +3454,24 @@ public: // Set the FP contractability status of this operator. Only meaningful for // operations on floating point types. - void setFPFeatures(FPOptions F) { FPFeatures = F.getInt(); } + void setFPFeatures(FPOptions F) { + BinaryOperatorBits.FPFeatures = F.getInt(); + } - FPOptions getFPFeatures() const { return FPOptions(FPFeatures); } + FPOptions getFPFeatures() const { + return FPOptions(BinaryOperatorBits.FPFeatures); + } // Get the FP contractability status of this operator. Only meaningful for // operations on floating point types. bool isFPContractableWithinStatement() const { - return FPOptions(FPFeatures).allowFPContractWithinStatement(); + return getFPFeatures().allowFPContractWithinStatement(); } + // Get the FENV_ACCESS status of this operator. Only meaningful for + // operations on floating point types. + bool isFEnvAccessOn() const { return getFPFeatures().allowFEnvAccess(); } + protected: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, @@ -3288,14 +3482,17 @@ protected: (lhs->isInstantiationDependent() || rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())), - Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) { + rhs->containsUnexpandedParameterPack())) { + BinaryOperatorBits.Opc = opc; + BinaryOperatorBits.FPFeatures = FPFeatures.getInt(); + BinaryOperatorBits.OpLoc = opLoc; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; } - BinaryOperator(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Opc(BO_MulAssign) { } + BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { + BinaryOperatorBits.Opc = BO_MulAssign; + } }; /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep @@ -3430,11 +3627,11 @@ public: Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } - SourceLocation getLocStart() const LLVM_READONLY { - return getCond()->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getCond()->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return getRHS()->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return getRHS()->getEndLoc(); } static bool classof(const Stmt *T) { @@ -3518,11 +3715,11 @@ public: return cast<Expr>(SubExprs[RHS]); } - SourceLocation getLocStart() const LLVM_READONLY { - return getCommon()->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getCommon()->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return getFalseExpr()->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return getFalseExpr()->getEndLoc(); } static bool classof(const Stmt *T) { @@ -3576,8 +3773,8 @@ public: SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return AmpAmpLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return AmpAmpLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return LabelLoc; } LabelDecl *getLabel() const { return Label; } void setLabel(LabelDecl *L) { Label = L; } @@ -3621,8 +3818,8 @@ public: const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); } void setSubStmt(CompoundStmt *S) { SubStmt = S; } - SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } @@ -3670,8 +3867,8 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ShuffleVectorExprClass; @@ -3754,8 +3951,8 @@ public: /// getRParenLoc - Return the location of final right parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ConvertVectorExprClass; @@ -3835,8 +4032,8 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ChooseExprClass; @@ -3874,8 +4071,8 @@ public: SourceLocation getTokenLocation() const { return TokenLoc; } void setTokenLocation(SourceLocation L) { TokenLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return TokenLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return TokenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return TokenLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return TokenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == GNUNullExprClass; @@ -3926,8 +4123,8 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == VAArgExprClass; @@ -4160,8 +4357,8 @@ public: InitListExprBits.HadArrayRangeDesignator = ARD; } - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == InitListExprClass; @@ -4395,17 +4592,17 @@ public: return ArrayOrRange.Index; } - SourceLocation getLocStart() const LLVM_READONLY { + SourceLocation getBeginLoc() const LLVM_READONLY { if (Kind == FieldDesignator) return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc(); else return getLBracketLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { + SourceLocation getEndLoc() const LLVM_READONLY { return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); } SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getLocStart(), getLocEnd()); + return SourceRange(getBeginLoc(), getEndLoc()); } }; @@ -4484,8 +4681,8 @@ public: SourceRange getDesignatorsSourceRange() const; - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == DesignatedInitExprClass; @@ -4526,8 +4723,8 @@ public: return T->getStmtClass() == NoInitExprClass; } - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); } // Iterators child_range children() { @@ -4561,8 +4758,8 @@ public: explicit DesignatedInitUpdateExpr(EmptyShell Empty) : Expr(DesignatedInitUpdateExprClass, Empty) { } - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == DesignatedInitUpdateExprClass; @@ -4636,11 +4833,11 @@ public: return S->getStmtClass() == ArrayInitLoopExprClass; } - SourceLocation getLocStart() const LLVM_READONLY { - return getCommonExpr()->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getCommonExpr()->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return getCommonExpr()->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return getCommonExpr()->getEndLoc(); } child_range children() { @@ -4671,8 +4868,8 @@ public: return S->getStmtClass() == ArrayInitIndexExprClass; } - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); } child_range children() { return child_range(child_iterator(), child_iterator()); @@ -4707,8 +4904,8 @@ public: return T->getStmtClass() == ImplicitValueInitExprClass; } - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); } // Iterators child_range children() { @@ -4719,31 +4916,46 @@ public: } }; -class ParenListExpr : public Expr { - Stmt **Exprs; - unsigned NumExprs; +class ParenListExpr final + : public Expr, + private llvm::TrailingObjects<ParenListExpr, Stmt *> { + friend class ASTStmtReader; + friend TrailingObjects; + + /// The location of the left and right parentheses. SourceLocation LParenLoc, RParenLoc; -public: - ParenListExpr(const ASTContext& C, SourceLocation lparenloc, - ArrayRef<Expr*> exprs, SourceLocation rparenloc); + /// Build a paren list. + ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs, + SourceLocation RParenLoc); /// Build an empty paren list. - explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } + ParenListExpr(EmptyShell Empty, unsigned NumExprs); + +public: + /// Create a paren list. + static ParenListExpr *Create(const ASTContext &Ctx, SourceLocation LParenLoc, + ArrayRef<Expr *> Exprs, + SourceLocation RParenLoc); - unsigned getNumExprs() const { return NumExprs; } + /// Create an empty paren list. + static ParenListExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumExprs); - const Expr* getExpr(unsigned Init) const { + /// Return the number of expressions in this paren list. + unsigned getNumExprs() const { return ParenListExprBits.NumExprs; } + + Expr *getExpr(unsigned Init) { assert(Init < getNumExprs() && "Initializer access out of range!"); - return cast_or_null<Expr>(Exprs[Init]); + return getExprs()[Init]; } - Expr* getExpr(unsigned Init) { - assert(Init < getNumExprs() && "Initializer access out of range!"); - return cast_or_null<Expr>(Exprs[Init]); + const Expr *getExpr(unsigned Init) const { + return const_cast<ParenListExpr *>(this)->getExpr(Init); } - Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); } + Expr **getExprs() { + return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>()); + } ArrayRef<Expr *> exprs() { return llvm::makeArrayRef(getExprs(), getNumExprs()); @@ -4751,9 +4963,8 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const { return getLParenLoc(); } + SourceLocation getEndLoc() const { return getRParenLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ParenListExprClass; @@ -4761,14 +4972,13 @@ public: // Iterators child_range children() { - return child_range(&Exprs[0], &Exprs[0]+NumExprs); + return child_range(getTrailingObjects<Stmt *>(), + getTrailingObjects<Stmt *>() + getNumExprs()); } const_child_range children() const { - return const_child_range(&Exprs[0], &Exprs[0] + NumExprs); + return const_child_range(getTrailingObjects<Stmt *>(), + getTrailingObjects<Stmt *>() + getNumExprs()); } - - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// Represents a C11 generic selection. @@ -4876,8 +5086,8 @@ public: const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); } Expr *getResultExpr() { return getAssocExpr(getResultIndex()); } - SourceLocation getLocStart() const LLVM_READONLY { return GenericLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return GenericLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == GenericSelectionExprClass; @@ -4942,10 +5152,10 @@ public: /// aggregate Constant of ConstantInt(s). void getEncodedElementAccess(SmallVectorImpl<uint32_t> &Elts) const; - SourceLocation getLocStart() const LLVM_READONLY { - return getBase()->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getBase()->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return AccessorLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return AccessorLoc; } /// isArrow - Return true if the base expression is a pointer to vector, /// return false if the base expression is a vector. @@ -4987,8 +5197,12 @@ public: const Stmt *getBody() const; Stmt *getBody(); - SourceLocation getLocStart() const LLVM_READONLY { return getCaretLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return getBody()->getLocEnd(); } + SourceLocation getBeginLoc() const LLVM_READONLY { + return getCaretLocation(); + } + SourceLocation getEndLoc() const LLVM_READONLY { + return getBody()->getEndLoc(); + } /// getFunctionType - Return the underlying function type for this block. const FunctionProtoType *getFunctionType() const; @@ -5040,8 +5254,8 @@ public: /// getRParenLoc - Return the location of final right parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == AsTypeExprClass; @@ -5182,11 +5396,11 @@ public: return getSyntacticForm()->getExprLoc(); } - SourceLocation getLocStart() const LLVM_READONLY { - return getSyntacticForm()->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getSyntacticForm()->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return getSyntacticForm()->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return getSyntacticForm()->getEndLoc(); } child_range children() { @@ -5309,8 +5523,8 @@ public: SourceLocation getBuiltinLoc() const { return BuiltinLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == AtomicExprClass; @@ -5363,8 +5577,8 @@ public: return const_child_range(const_child_iterator(), const_child_iterator()); } - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); } static bool classof(const Stmt *T) { return T->getStmtClass() == TypoExprClass; |
