summaryrefslogtreecommitdiff
path: root/lib/AST/Decl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r--lib/AST/Decl.cpp143
1 files changed, 112 insertions, 31 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 4c1d591b41e9c..3b9b85a20af6f 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -27,6 +27,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ODRHash.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Stmt.h"
@@ -76,6 +77,24 @@ Decl *clang::getPrimaryMergedDecl(Decl *D) {
return D->getASTContext().getPrimaryMergedDecl(D);
}
+void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
+ SourceLocation Loc = this->Loc;
+ if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
+ if (Loc.isValid()) {
+ Loc.print(OS, Context.getSourceManager());
+ OS << ": ";
+ }
+ OS << Message;
+
+ if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
+ OS << " '";
+ ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
+ OS << "'";
+ }
+
+ OS << '\n';
+}
+
// Defined here so that it can be inlined into its direct callers.
bool Decl::isOutOfLine() const {
return !getLexicalDeclContext()->Equals(getDeclContext());
@@ -224,7 +243,7 @@ LinkageInfo LinkageComputer::getLVForType(const Type &T,
return getTypeLinkageAndVisibility(&T);
}
-/// \brief Get the most restrictive linkage for the types in the given
+/// Get the most restrictive linkage for the types in the given
/// template parameter list. For visibility purposes, template
/// parameters are part of the signature of a template.
LinkageInfo LinkageComputer::getLVForTemplateParameterList(
@@ -291,7 +310,7 @@ static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
return Ret;
}
-/// \brief Get the most restrictive linkage for the types and
+/// Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
///
/// Note that we don't take an LVComputationKind because we always
@@ -312,12 +331,12 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
LV.merge(getLVForType(*Arg.getAsType(), computation));
continue;
- case TemplateArgument::Declaration:
- if (const auto *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) {
- assert(!usesTypeVisibility(ND));
- LV.merge(getLVForDecl(ND, computation));
- }
+ case TemplateArgument::Declaration: {
+ const NamedDecl *ND = Arg.getAsDecl();
+ assert(!usesTypeVisibility(ND));
+ LV.merge(getLVForDecl(ND, computation));
continue;
+ }
case TemplateArgument::NullPtr:
LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
@@ -779,7 +798,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// unique-external linkage, it's not legally usable from outside
// this translation unit. However, we should use the C linkage
// rules instead for extern "C" declarations.
- if (Context.getLangOpts().CPlusPlus && !Function->isInExternCContext()) {
+ if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Function)) {
// Only look at the type-as-written. Otherwise, deducing the return type
// of a function could change its linkage.
QualType TypeAsWritten = Function->getType();
@@ -1073,9 +1092,18 @@ getExplicitVisibilityAux(const NamedDecl *ND,
// If there wasn't explicit visibility there, and this is a
// specialization of a class template, check for visibility
// on the pattern.
- if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND))
- return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
- kind);
+ if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ // Walk all the template decl till this point to see if there are
+ // explicit visibility attributes.
+ const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl();
+ while (TD != nullptr) {
+ auto Vis = getVisibilityOf(TD, kind);
+ if (Vis != None)
+ return Vis;
+ TD = TD->getPreviousDecl();
+ }
+ return None;
+ }
// Use the most recent declaration.
if (!IsMostRecent && !isa<NamespaceDecl>(ND)) {
@@ -1165,7 +1193,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
LVComputationKind computation) {
if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
if (Function->isInAnonymousNamespace() &&
- !Function->isInExternCContext())
+ !isFirstInExternCContext(Function))
return getInternalLinkageFor(Function);
// This is a "void f();" which got merged with a file static.
@@ -1188,7 +1216,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
if (const auto *Var = dyn_cast<VarDecl>(D)) {
if (Var->hasExternalStorage()) {
- if (Var->isInAnonymousNamespace() && !Var->isInExternCContext())
+ if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var))
return getInternalLinkageFor(Var);
LinkageInfo LV;
@@ -1497,9 +1525,10 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
using ContextsTy = SmallVector<const DeclContext *, 8>;
ContextsTy Contexts;
- // Collect contexts.
- while (Ctx && isa<NamedDecl>(Ctx)) {
- Contexts.push_back(Ctx);
+ // Collect named contexts.
+ while (Ctx) {
+ if (isa<NamedDecl>(Ctx))
+ Contexts.push_back(Ctx);
Ctx = Ctx->getParent();
}
@@ -2403,6 +2432,23 @@ void VarDecl::setDescribedVarTemplate(VarTemplateDecl *Template) {
getASTContext().setTemplateOrSpecializationInfo(this, Template);
}
+bool VarDecl::isKnownToBeDefined() const {
+ const auto &LangOpts = getASTContext().getLangOpts();
+ // In CUDA mode without relocatable device code, variables of form 'extern
+ // __shared__ Foo foo[]' are pointers to the base of the GPU core's shared
+ // memory pool. These are never undefined variables, even if they appear
+ // inside of an anon namespace or static function.
+ //
+ // With CUDA relocatable device code enabled, these variables don't get
+ // special handling; they're treated like regular extern variables.
+ if (LangOpts.CUDA && !LangOpts.CUDARelocatableDeviceCode &&
+ hasExternalStorage() && hasAttr<CUDASharedAttr>() &&
+ isa<IncompleteArrayType>(getType()))
+ return true;
+
+ return hasDefinition();
+}
+
MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
if (isStaticDataMember())
// FIXME: Remove ?
@@ -2827,6 +2873,14 @@ bool FunctionDecl::isNoReturn() const {
return false;
}
+bool FunctionDecl::isCPUDispatchMultiVersion() const {
+ return isMultiVersion() && hasAttr<CPUDispatchAttr>();
+}
+
+bool FunctionDecl::isCPUSpecificMultiVersion() const {
+ return isMultiVersion() && hasAttr<CPUSpecificAttr>();
+}
+
void
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
redeclarable_base::setPreviousDecl(PrevDecl);
@@ -2844,7 +2898,7 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
-/// \brief Returns a value indicating whether this function
+/// Returns a value indicating whether this function
/// corresponds to a builtin function.
///
/// The function corresponds to a built-in function if it is
@@ -2901,6 +2955,13 @@ unsigned FunctionDecl::getBuiltinID() const {
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return 0;
+ // CUDA does not have device-side standard library. printf and malloc are the
+ // only special cases that are supported by device-side runtime.
+ if (Context.getLangOpts().CUDA && hasAttr<CUDADeviceAttr>() &&
+ !hasAttr<CUDAHostAttr>() &&
+ !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
+ return 0;
+
return BuiltinID;
}
@@ -2939,7 +3000,7 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
return NumRequiredArgs;
}
-/// \brief The combination of the extern and inline keywords under MSVC forces
+/// The combination of the extern and inline keywords under MSVC forces
/// the function to be required.
///
/// Note: This function assumes that we will only get called when isInlined()
@@ -2988,7 +3049,7 @@ static bool RedeclForcesDefC99(const FunctionDecl *Redecl) {
return false;
}
-/// \brief For a function declaration in C or C++, determine whether this
+/// For a function declaration in C or C++, determine whether this
/// declaration causes the definition to be externally visible.
///
/// For instance, this determines if adding the current declaration to the set
@@ -3103,7 +3164,7 @@ const Attr *FunctionDecl::getUnusedResultAttr() const {
return getAttr<WarnUnusedResultAttr>();
}
-/// \brief For an inline function definition in C, or for a gnu_inline function
+/// For an inline function definition in C, or for a gnu_inline function
/// in C++, determine whether the definition will be externally visible.
///
/// Inline function definitions are always available for inlining optimizations.
@@ -3605,16 +3666,19 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
return 0;
}
+unsigned FunctionDecl::getODRHash() const {
+ assert(HasODRHash);
+ return ODRHash;
+}
+
unsigned FunctionDecl::getODRHash() {
if (HasODRHash)
return ODRHash;
- if (FunctionDecl *Definition = getDefinition()) {
- if (Definition != this) {
- HasODRHash = true;
- ODRHash = Definition->getODRHash();
- return ODRHash;
- }
+ if (auto *FT = getInstantiatedFromMemberFunction()) {
+ HasODRHash = true;
+ ODRHash = FT->getODRHash();
+ return ODRHash;
}
class ODRHash Hash;
@@ -3658,6 +3722,11 @@ unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue();
}
+bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const {
+ return isUnnamedBitfield() && !getBitWidth()->isValueDependent() &&
+ getBitWidthValue(Ctx) == 0;
+}
+
unsigned FieldDecl::getFieldIndex() const {
const FieldDecl *Canonical = getCanonicalDecl();
if (Canonical != this)
@@ -3904,6 +3973,17 @@ void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK);
}
+unsigned EnumDecl::getODRHash() {
+ if (HasODRHash)
+ return ODRHash;
+
+ class ODRHash Hash;
+ Hash.AddEnumDecl(this);
+ HasODRHash = true;
+ ODRHash = Hash.CalculateHash();
+ return ODRHash;
+}
+
//===----------------------------------------------------------------------===//
// RecordDecl Implementation
//===----------------------------------------------------------------------===//
@@ -3915,7 +3995,10 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
: TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc),
HasFlexibleArrayMember(false), AnonymousStructOrUnion(false),
HasObjectMember(false), HasVolatileMember(false),
- LoadedFieldsFromExternalStorage(false) {
+ LoadedFieldsFromExternalStorage(false),
+ NonTrivialToPrimitiveDefaultInitialize(false),
+ NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false),
+ ParamDestroyedInCallee(false), ArgPassingRestrictions(APK_CanPassInRegs) {
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
}
@@ -4365,9 +4448,7 @@ bool TypedefNameDecl::isTransparentTagSlow() const {
};
bool isTransparent = determineIsTransparent();
- CacheIsTransparentTag = 1;
- if (isTransparent)
- CacheIsTransparentTag |= 0x2;
+ MaybeModedTInfo.setInt((isTransparent << 1) | 1);
return isTransparent;
}
@@ -4433,7 +4514,7 @@ EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
// ImportDecl Implementation
//===----------------------------------------------------------------------===//
-/// \brief Retrieve the number of module identifiers needed to name the given
+/// Retrieve the number of module identifiers needed to name the given
/// module.
static unsigned getNumModuleIdentifiers(Module *Mod) {
unsigned Result = 1;