summaryrefslogtreecommitdiffstats
path: root/include/clang/AST/Decl.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/Decl.h')
-rw-r--r--include/clang/AST/Decl.h219
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
OpenPOWER on IntegriCloud