summaryrefslogtreecommitdiffstats
path: root/include/clang/AST/DeclBase.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/DeclBase.h')
-rw-r--r--include/clang/AST/DeclBase.h163
1 files changed, 126 insertions, 37 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 754facf..26eea64 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -16,6 +16,7 @@
#include "clang/AST/AttrIterator.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/Linkage.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Compiler.h"
@@ -31,6 +32,7 @@ class DeclarationName;
class DependentDiagnostic;
class EnumDecl;
class FunctionDecl;
+class LinkageComputer;
class LinkageSpecDecl;
class Module;
class NamedDecl;
@@ -157,7 +159,12 @@ public:
/// This declaration is a C++ operator declared in a non-class
/// context. All such operators are also in IDNS_Ordinary.
/// C++ lexical operator lookup looks for these.
- IDNS_NonMemberOperator = 0x0400
+ IDNS_NonMemberOperator = 0x0400,
+
+ /// This declaration is a function-local extern declaration of a
+ /// variable or function. This may also be IDNS_Ordinary if it
+ /// has been declared outside any function.
+ IDNS_LocalExtern = 0x0800
};
/// ObjCDeclQualifier - 'Qualifiers' written next to the return and
@@ -284,19 +291,16 @@ protected:
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 12;
- /// \brief Whether the \c CachedLinkage field is active.
- ///
- /// This field is only valid for NamedDecls subclasses.
- mutable unsigned HasCachedLinkage : 1;
-
- /// \brief If \c HasCachedLinkage, the linkage of this declaration.
- ///
- /// This field is only valid for NamedDecls subclasses.
- mutable unsigned CachedLinkage : 2;
+ /// \brief If 0, we have not computed the linkage of this declaration.
+ /// Otherwise, it is the linkage + 1.
+ mutable unsigned CacheValidAndLinkage : 3;
friend class ASTDeclWriter;
friend class ASTDeclReader;
friend class ASTReader;
+ friend class LinkageComputer;
+
+ template<typename decl_type> friend class Redeclarable;
private:
void CheckAccessDeclContext() const;
@@ -309,7 +313,7 @@ protected:
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
- HasCachedLinkage(0)
+ CacheValidAndLinkage(0)
{
if (StatisticsEnabled) add(DK);
}
@@ -319,7 +323,7 @@ protected:
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
- HasCachedLinkage(0)
+ CacheValidAndLinkage(0)
{
if (StatisticsEnabled) add(DK);
}
@@ -341,6 +345,18 @@ protected:
/// \brief Update a potentially out-of-date declaration.
void updateOutOfDate(IdentifierInfo &II) const;
+ Linkage getCachedLinkage() const {
+ return Linkage(CacheValidAndLinkage - 1);
+ }
+
+ void setCachedLinkage(Linkage L) const {
+ CacheValidAndLinkage = L + 1;
+ }
+
+ bool hasCachedLinkage() const {
+ return CacheValidAndLinkage;
+ }
+
public:
/// \brief Source range that this declaration covers.
@@ -419,7 +435,6 @@ public:
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
const AttrVec &getAttrs() const;
- void swapAttrs(Decl *D);
void dropAttrs();
void addAttr(Attr *A) {
@@ -490,7 +505,16 @@ public:
/// whether the function is used.
bool isUsed(bool CheckUsedAttr = true) const;
- void setUsed(bool U = true) { Used = U; }
+ /// \brief Set whether the declaration is used, in the sense of odr-use.
+ ///
+ /// This should only be used immediately after creating a declaration.
+ void setIsUsed() { Used = true; }
+
+ /// \brief Mark the declaration used, in the sense of odr-use.
+ ///
+ /// This notifies any mutation listeners in addition to setting a bit
+ /// indicating the declaration is used.
+ void markUsed(ASTContext &C);
/// \brief Whether this declaration was referenced.
bool isReferenced() const;
@@ -513,13 +537,13 @@ public:
NextInContextAndBits.setInt(Bits);
}
-protected:
/// \brief Whether this declaration was marked as being private to the
/// module in which it was defined.
- bool isModulePrivate() const {
+ bool isModulePrivate() const {
return NextInContextAndBits.getInt() & ModulePrivateFlag;
}
-
+
+protected:
/// \brief Specify whether this declaration was marked as being private
/// to the module in which it was defined.
void setModulePrivate(bool MP = true) {
@@ -761,7 +785,12 @@ public:
const Decl *getPreviousDecl() const {
return const_cast<Decl *>(this)->getPreviousDeclImpl();
}
-
+
+ /// \brief True if this is the first declaration in its redeclaration chain.
+ bool isFirstDecl() const {
+ return getPreviousDecl() == 0;
+ }
+
/// \brief Retrieve the most recent declaration that declares the same entity
/// as this declaration (which may be this declaration).
Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); }
@@ -777,8 +806,10 @@ public:
/// top-level Stmt* of that body. Otherwise this method returns null.
virtual Stmt* getBody() const { return 0; }
- /// \brief Returns true if this Decl represents a declaration for a body of
+ /// \brief Returns true if this \c Decl represents a declaration for a body of
/// code, such as a function or method definition.
+ /// Note that \c hasBody can also return true if any redeclaration of this
+ /// \c Decl represents a declaration for a body of code.
virtual bool hasBody() const { return getBody() != 0; }
/// getBodyRBrace - Gets the right brace of the body, if a body exists.
@@ -808,37 +839,71 @@ public:
bool isFunctionOrFunctionTemplate() const;
/// \brief Changes the namespace of this declaration to reflect that it's
+ /// a function-local extern declaration.
+ ///
+ /// These declarations appear in the lexical context of the extern
+ /// declaration, but in the semantic context of the enclosing namespace
+ /// scope.
+ void setLocalExternDecl() {
+ assert((IdentifierNamespace == IDNS_Ordinary ||
+ IdentifierNamespace == IDNS_OrdinaryFriend) &&
+ "namespace is not ordinary");
+
+ Decl *Prev = getPreviousDecl();
+ IdentifierNamespace &= ~IDNS_Ordinary;
+
+ IdentifierNamespace |= IDNS_LocalExtern;
+ if (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary)
+ IdentifierNamespace |= IDNS_Ordinary;
+ }
+
+ /// \brief Determine whether this is a block-scope declaration with linkage.
+ /// This will either be a local variable declaration declared 'extern', or a
+ /// local function declaration.
+ bool isLocalExternDecl() {
+ return IdentifierNamespace & IDNS_LocalExtern;
+ }
+
+ /// \brief Changes the namespace of this declaration to reflect that it's
/// the object of a friend declaration.
///
/// These declarations appear in the lexical context of the friending
/// class, but in the semantic context of the actual entity. This property
/// applies only to a specific decl object; other redeclarations of the
/// same entity may not (and probably don't) share this property.
- void setObjectOfFriendDecl(bool PreviouslyDeclared) {
+ void setObjectOfFriendDecl(bool PerformFriendInjection = false) {
unsigned OldNS = IdentifierNamespace;
assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
- IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
+ IDNS_TagFriend | IDNS_OrdinaryFriend |
+ IDNS_LocalExtern)) &&
"namespace includes neither ordinary nor tag");
assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type |
- IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
+ IDNS_TagFriend | IDNS_OrdinaryFriend |
+ IDNS_LocalExtern)) &&
"namespace includes other than ordinary or tag");
- IdentifierNamespace = 0;
+ Decl *Prev = getPreviousDecl();
+ IdentifierNamespace &= ~(IDNS_Ordinary | IDNS_Tag | IDNS_Type);
+
if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
IdentifierNamespace |= IDNS_TagFriend;
- if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type;
+ if (PerformFriendInjection ||
+ (Prev && Prev->getIdentifierNamespace() & IDNS_Tag))
+ IdentifierNamespace |= IDNS_Tag | IDNS_Type;
}
- if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
+ if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend | IDNS_LocalExtern)) {
IdentifierNamespace |= IDNS_OrdinaryFriend;
- if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary;
+ if (PerformFriendInjection ||
+ (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary))
+ IdentifierNamespace |= IDNS_Ordinary;
}
}
enum FriendObjectKind {
- FOK_None, // not a friend object
- FOK_Declared, // a friend of a previously-declared entity
- FOK_Undeclared // a friend of a previously-undeclared entity
+ FOK_None, ///< Not a friend object.
+ FOK_Declared, ///< A friend of a previously-declared entity.
+ FOK_Undeclared ///< A friend of a previously-undeclared entity.
};
/// \brief Determines whether this declaration is the object of a
@@ -846,11 +911,11 @@ public:
///
/// There is currently no direct way to find the associated FriendDecl.
FriendObjectKind getFriendObjectKind() const {
- unsigned mask
- = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend));
+ unsigned mask =
+ (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend));
if (!mask) return FOK_None;
- return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ?
- FOK_Declared : FOK_Undeclared);
+ return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? FOK_Declared
+ : FOK_Undeclared);
}
/// Specifies that this declaration is a C++ overloaded non-member.
@@ -877,9 +942,6 @@ public:
// Same as dump(), but forces color printing.
LLVM_ATTRIBUTE_USED void dumpColor() const;
void dump(raw_ostream &Out) const;
- // Debuggers don't usually respect default arguments.
- LLVM_ATTRIBUTE_USED void dumpXML() const;
- void dumpXML(raw_ostream &OS) const;
private:
void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx);
@@ -974,6 +1036,7 @@ protected:
mutable Decl *LastDecl;
friend class ExternalASTSource;
+ friend class ASTDeclReader;
friend class ASTWriter;
/// \brief Build up a chain of declarations.
@@ -1096,6 +1159,14 @@ public:
/// C++0x scoped enums), and C++ linkage specifications.
bool isTransparentContext() const;
+ /// \brief Determines whether this context or some of its ancestors is a
+ /// linkage specification context that specifies C linkage.
+ bool isExternCContext() const;
+
+ /// \brief Determines whether this context or some of its ancestors is a
+ /// linkage specification context that specifies C++ linkage.
+ bool isExternCXXContext() const;
+
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
bool Equals(const DeclContext *DC) const {
@@ -1429,12 +1500,20 @@ public:
return const_cast<DeclContext*>(this)->lookup(Name);
}
+ /// \brief Find the declarations with the given name that are visible
+ /// within this context; don't attempt to retrieve anything from an
+ /// external source.
+ lookup_result noload_lookup(DeclarationName Name);
+
/// \brief A simplistic name lookup mechanism that performs name lookup
/// into this declaration context without consulting the external source.
///
/// This function should almost never be used, because it subverts the
/// usual relationship between a DeclContext and the external source.
/// See the ASTImporter for the (few, but important) use cases.
+ ///
+ /// FIXME: This is very inefficient; replace uses of it with uses of
+ /// noload_lookup.
void localUncachedLookup(DeclarationName Name,
SmallVectorImpl<NamedDecl *> &Results);
@@ -1458,10 +1537,16 @@ public:
/// of looking up every possible name.
class all_lookups_iterator;
+ /// \brief Iterators over all possible lookups within this context.
all_lookups_iterator lookups_begin() const;
-
all_lookups_iterator lookups_end() const;
+ /// \brief Iterators over all possible lookups within this context that are
+ /// currently loaded; don't attempt to retrieve anything from an external
+ /// source.
+ all_lookups_iterator noload_lookups_begin() const;
+ all_lookups_iterator noload_lookups_end() const;
+
/// udir_iterator - Iterates through the using-directives stored
/// within this context.
typedef UsingDirectiveDecl * const * udir_iterator;
@@ -1532,6 +1617,8 @@ public:
static bool classof(const DeclContext *D) { return true; }
LLVM_ATTRIBUTE_USED void dumpDeclContext() const;
+ LLVM_ATTRIBUTE_USED void dumpLookups() const;
+ LLVM_ATTRIBUTE_USED void dumpLookups(llvm::raw_ostream &OS) const;
private:
void reconcileExternalVisibleStorage();
@@ -1548,6 +1635,8 @@ private:
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
+ template<decl_iterator (DeclContext::*Begin)() const,
+ decl_iterator (DeclContext::*End)() const>
void buildLookupImpl(DeclContext *DCtx);
void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
bool Rediscoverable);
OpenPOWER on IntegriCloud