diff options
Diffstat (limited to 'include/clang/AST/Decl.h')
-rw-r--r-- | include/clang/AST/Decl.h | 219 |
1 files changed, 156 insertions, 63 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index a39888f..451f9da 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -39,6 +39,7 @@ class LabelStmt; class MemberSpecializationInfo; class Module; class NestedNameSpecifier; +class ParmVarDecl; class Stmt; class StringLiteral; class TemplateArgumentList; @@ -82,10 +83,7 @@ class TranslationUnitDecl : public Decl, public DeclContext { /// translation unit, if one has been created. NamespaceDecl *AnonymousNamespace; - explicit TranslationUnitDecl(ASTContext &ctx) - : Decl(TranslationUnit, nullptr, SourceLocation()), - DeclContext(TranslationUnit), - Ctx(ctx), AnonymousNamespace(nullptr) {} + explicit TranslationUnitDecl(ASTContext &ctx); public: ASTContext &getASTContext() const { return Ctx; } @@ -104,6 +102,43 @@ public: } }; +/// \brief Declaration context for names declared as extern "C" in C++. This +/// is neither the semantic nor lexical context for such declarations, but is +/// used to check for conflicts with other extern "C" declarations. Example: +/// +/// \code +/// namespace N { extern "C" void f(); } // #1 +/// void N::f() {} // #2 +/// namespace M { extern "C" void f(); } // #3 +/// \endcode +/// +/// The semantic context of #1 is namespace N and its lexical context is the +/// LinkageSpecDecl; the semantic context of #2 is namespace N and its lexical +/// context is the TU. However, both declarations are also visible in the +/// extern "C" context. +/// +/// The declaration at #3 finds it is a redeclaration of \c N::f through +/// lookup in the extern "C" context. +class ExternCContextDecl : public Decl, public DeclContext { + virtual void anchor(); + + explicit ExternCContextDecl(TranslationUnitDecl *TU) + : Decl(ExternCContext, TU, SourceLocation()), + DeclContext(ExternCContext) {} +public: + static ExternCContextDecl *Create(const ASTContext &C, + TranslationUnitDecl *TU); + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == ExternCContext; } + static DeclContext *castToDeclContext(const ExternCContextDecl *D) { + return static_cast<DeclContext *>(const_cast<ExternCContextDecl*>(D)); + } + static ExternCContextDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<ExternCContextDecl *>(const_cast<DeclContext*>(DC)); + } +}; + /// NamedDecl - This represents a decl with a name. Many decls have names such /// as ObjCMethodDecl, but not \@class, etc. class NamedDecl : public Decl { @@ -179,14 +214,17 @@ public: const PrintingPolicy &Policy, bool Qualified) const; - /// declarationReplaces - Determine whether this declaration, if + /// \brief Determine whether this declaration, if /// known to be well-formed within its context, will replace the /// declaration OldD if introduced into scope. A declaration will /// replace another declaration if, for example, it is a /// redeclaration of the same variable or function, but not if it is /// a declaration of a different kind (function vs. class) or an /// overloaded function. - bool declarationReplaces(NamedDecl *OldD) const; + /// + /// \param IsKnownNewer \c true if this declaration is known to be newer + /// than \p OldD (for instance, if this declaration is newly-created). + bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer = true) const; /// \brief Determine whether this declaration has linkage. bool hasLinkage() const; @@ -535,8 +573,8 @@ struct QualifierInfo { private: // Copy constructor and copy assignment are disabled. - QualifierInfo(const QualifierInfo&) LLVM_DELETED_FUNCTION; - QualifierInfo& operator=(const QualifierInfo&) LLVM_DELETED_FUNCTION; + QualifierInfo(const QualifierInfo&) = delete; + QualifierInfo& operator=(const QualifierInfo&) = delete; }; /// \brief Represents a ValueDecl that came out of a declarator. @@ -710,37 +748,8 @@ private: unsigned SClass : 3; unsigned TSCSpec : 2; unsigned InitStyle : 2; - - /// \brief Whether this variable is the exception variable in a C++ catch - /// or an Objective-C @catch statement. - unsigned ExceptionVar : 1; - - /// \brief Whether this local variable could be allocated in the return - /// slot of its function, enabling the named return value optimization - /// (NRVO). - unsigned NRVOVariable : 1; - - /// \brief Whether this variable is the for-range-declaration in a C++0x - /// for-range statement. - unsigned CXXForRangeDecl : 1; - - /// \brief Whether this variable is an ARC pseudo-__strong - /// variable; see isARCPseudoStrong() for details. - unsigned ARCPseudoStrong : 1; - - /// \brief Whether this variable is (C++0x) constexpr. - unsigned IsConstexpr : 1; - - /// \brief Whether this variable is the implicit variable for a lambda - /// init-capture. - unsigned IsInitCapture : 1; - - /// \brief Whether this local extern variable's previous declaration was - /// declared in the same block scope. This controls whether we should merge - /// the type of this declaration with its previous declaration. - unsigned PreviousDeclInSameBlockScope : 1; }; - enum { NumVarDeclBits = 14 }; + enum { NumVarDeclBits = 7 }; friend class ASTDeclReader; friend class StmtIteratorBase; @@ -776,10 +785,47 @@ protected: unsigned ParameterIndex : NumParameterIndexBits; }; + class NonParmVarDeclBitfields { + friend class VarDecl; + friend class ASTDeclReader; + + unsigned : NumVarDeclBits; + + /// \brief Whether this variable is the exception variable in a C++ catch + /// or an Objective-C @catch statement. + unsigned ExceptionVar : 1; + + /// \brief Whether this local variable could be allocated in the return + /// slot of its function, enabling the named return value optimization + /// (NRVO). + unsigned NRVOVariable : 1; + + /// \brief Whether this variable is the for-range-declaration in a C++0x + /// for-range statement. + unsigned CXXForRangeDecl : 1; + + /// \brief Whether this variable is an ARC pseudo-__strong + /// variable; see isARCPseudoStrong() for details. + unsigned ARCPseudoStrong : 1; + + /// \brief Whether this variable is (C++0x) constexpr. + unsigned IsConstexpr : 1; + + /// \brief Whether this variable is the implicit variable for a lambda + /// init-capture. + unsigned IsInitCapture : 1; + + /// \brief Whether this local extern variable's previous declaration was + /// declared in the same block scope. This controls whether we should merge + /// the type of this declaration with its previous declaration. + unsigned PreviousDeclInSameBlockScope : 1; + }; + union { unsigned AllBits; VarDeclBitfields VarDeclBits; ParmVarDeclBitfields ParmVarDeclBits; + NonParmVarDeclBitfields NonParmVarDeclBits; }; VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, @@ -840,7 +886,7 @@ public: return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified; // Global Named Register (GNU extension) - if (getStorageClass() == SC_Register && !isLocalVarDecl()) + if (getStorageClass() == SC_Register && !isLocalVarDeclOrParm()) return false; // Return true for: Auto, Register. @@ -1132,9 +1178,12 @@ public: /// \brief Determine whether this variable is the exception variable in a /// C++ catch statememt or an Objective-C \@catch statement. bool isExceptionVariable() const { - return VarDeclBits.ExceptionVar; + return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ExceptionVar; + } + void setExceptionVariable(bool EV) { + assert(!isa<ParmVarDecl>(this)); + NonParmVarDeclBits.ExceptionVar = EV; } - void setExceptionVariable(bool EV) { VarDeclBits.ExceptionVar = EV; } /// \brief Determine whether this local variable can be used with the named /// return value optimization (NRVO). @@ -1146,36 +1195,64 @@ public: /// return slot when returning from the function. Within the function body, /// each return that returns the NRVO object will have this variable as its /// NRVO candidate. - bool isNRVOVariable() const { return VarDeclBits.NRVOVariable; } - void setNRVOVariable(bool NRVO) { VarDeclBits.NRVOVariable = NRVO; } + bool isNRVOVariable() const { + return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.NRVOVariable; + } + void setNRVOVariable(bool NRVO) { + assert(!isa<ParmVarDecl>(this)); + NonParmVarDeclBits.NRVOVariable = NRVO; + } /// \brief Determine whether this variable is the for-range-declaration in /// a C++0x for-range statement. - bool isCXXForRangeDecl() const { return VarDeclBits.CXXForRangeDecl; } - void setCXXForRangeDecl(bool FRD) { VarDeclBits.CXXForRangeDecl = FRD; } + bool isCXXForRangeDecl() const { + return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.CXXForRangeDecl; + } + void setCXXForRangeDecl(bool FRD) { + assert(!isa<ParmVarDecl>(this)); + NonParmVarDeclBits.CXXForRangeDecl = FRD; + } /// \brief Determine whether this variable is an ARC pseudo-__strong /// variable. A pseudo-__strong variable has a __strong-qualified /// type but does not actually retain the object written into it. /// Generally such variables are also 'const' for safety. - bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; } - void setARCPseudoStrong(bool ps) { VarDeclBits.ARCPseudoStrong = ps; } + bool isARCPseudoStrong() const { + return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ARCPseudoStrong; + } + void setARCPseudoStrong(bool ps) { + assert(!isa<ParmVarDecl>(this)); + NonParmVarDeclBits.ARCPseudoStrong = ps; + } /// Whether this variable is (C++11) constexpr. - bool isConstexpr() const { return VarDeclBits.IsConstexpr; } - void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; } + bool isConstexpr() const { + return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConstexpr; + } + void setConstexpr(bool IC) { + assert(!isa<ParmVarDecl>(this)); + NonParmVarDeclBits.IsConstexpr = IC; + } /// Whether this variable is the implicit variable for a lambda init-capture. - bool isInitCapture() const { return VarDeclBits.IsInitCapture; } - void setInitCapture(bool IC) { VarDeclBits.IsInitCapture = IC; } + bool isInitCapture() const { + return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture; + } + void setInitCapture(bool IC) { + assert(!isa<ParmVarDecl>(this)); + NonParmVarDeclBits.IsInitCapture = IC; + } /// Whether this local extern variable declaration's previous declaration /// was declared in the same block scope. Only correct in C++. bool isPreviousDeclInSameBlockScope() const { - return VarDeclBits.PreviousDeclInSameBlockScope; + return isa<ParmVarDecl>(this) + ? false + : NonParmVarDeclBits.PreviousDeclInSameBlockScope; } void setPreviousDeclInSameBlockScope(bool Same) { - VarDeclBits.PreviousDeclInSameBlockScope = Same; + assert(!isa<ParmVarDecl>(this)); + NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same; } /// \brief If this variable is an instantiated static data member of a @@ -1482,6 +1559,9 @@ private: bool IsLateTemplateParsed : 1; bool IsConstexpr : 1; + /// \brief Indicates if the function uses __try. + bool UsesSEHTry : 1; + /// \brief Indicates if the function was a definition but its body was /// skipped. unsigned HasSkippedBody : 1; @@ -1570,8 +1650,8 @@ protected: HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsDefaulted(false), IsExplicitlyDefaulted(false), HasImplicitReturnZero(false), IsLateTemplateParsed(false), - IsConstexpr(isConstexprSpecified), HasSkippedBody(false), - EndRangeLoc(NameInfo.getEndLoc()), + IsConstexpr(isConstexprSpecified), UsesSEHTry(false), + HasSkippedBody(false), EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(), DNLoc(NameInfo.getInfo()) {} @@ -1751,6 +1831,10 @@ public: bool isConstexpr() const { return IsConstexpr; } void setConstexpr(bool IC) { IsConstexpr = IC; } + /// Whether this is a (C++11) constexpr function or constexpr constructor. + bool usesSEHTry() const { return UsesSEHTry; } + void setUsesSEHTry(bool UST) { UsesSEHTry = UST; } + /// \brief Whether this function has been deleted. /// /// A function that is "deleted" (via the C++0x "= delete" syntax) @@ -1814,11 +1898,6 @@ public: /// allocation function. [...] bool isReplaceableGlobalAllocationFunction() const; - /// \brief Determine whether this function is a sized global deallocation - /// function in C++1y. If so, find and return the corresponding unsized - /// deallocation function. - FunctionDecl *getCorrespondingUnsizedGlobalDeallocationFunction() const; - /// Compute the language linkage. LanguageLinkage getLanguageLinkage() const; @@ -1847,8 +1926,10 @@ public: void setPreviousDeclaration(FunctionDecl * PrevDecl); - virtual const FunctionDecl *getCanonicalDecl() const; FunctionDecl *getCanonicalDecl() override; + const FunctionDecl *getCanonicalDecl() const { + return const_cast<FunctionDecl*>(this)->getCanonicalDecl(); + } unsigned getBuiltinID() const; @@ -1923,6 +2004,13 @@ public: return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); } + /// \brief Returns true if this function or its return type has the + /// warn_unused_result attribute. If the return type has the attribute and + /// this function is a method of the return type's class, then false will be + /// returned to avoid spurious warnings on member methods such as assignment + /// operators. + bool hasUnusedResultAttr() const; + /// \brief Returns the storage class as written in the source. For the /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return StorageClass(SClass); } @@ -2537,6 +2625,13 @@ public: TypedefNameDecl *getCanonicalDecl() override { return getFirstDecl(); } const TypedefNameDecl *getCanonicalDecl() const { return getFirstDecl(); } + /// Retrieves the tag declaration for which this is the typedef name for + /// linkage purposes, if any. + /// + /// \param AnyRedecl Look for the tag declaration in any redeclaration of + /// this typedef declaration. + TagDecl *getAnonDeclWithTypedefName(bool AnyRedecl = false) const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { @@ -3696,8 +3791,6 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) { assert(RedeclLink.NextIsLatest() && "setPreviousDecl on a decl already in a redeclaration chain"); - decl_type *First; - if (PrevDecl) { // Point to previous. Make sure that this is actually the most recent // redeclaration, or we can build invalid chains. If the most recent |