forked from OSchip/llvm-project
Make all 'is in extern "C"' tests use the lexical context.
I was not able to find a case (other than the fix in r181163) where this makes a difference, but it is a more obviously correct API to have. llvm-svn: 181165
This commit is contained in:
parent
1debc468fa
commit
593537a979
|
@ -830,6 +830,14 @@ public:
|
|||
/// external, C linkage.
|
||||
bool isExternC() const;
|
||||
|
||||
/// \brief Determines whether this variable's context is, or is nested within,
|
||||
/// a C++ extern "C" linkage spec.
|
||||
bool isInExternCContext() const;
|
||||
|
||||
/// \brief Determines whether this variable's context is, or is nested within,
|
||||
/// a C++ extern "C++" linkage spec.
|
||||
bool isInExternCXXContext() const;
|
||||
|
||||
/// isLocalVarDecl - Returns true for local variable declarations
|
||||
/// other than parameters. Note that this includes static variables
|
||||
/// inside of functions. It also includes variables inside blocks.
|
||||
|
@ -1715,6 +1723,14 @@ public:
|
|||
/// external, C linkage.
|
||||
bool isExternC() const;
|
||||
|
||||
/// \brief Determines whether this function's context is, or is nested within,
|
||||
/// a C++ extern "C" linkage spec.
|
||||
bool isInExternCContext() const;
|
||||
|
||||
/// \brief Determines whether this function's context is, or is nested within,
|
||||
/// a C++ extern "C++" linkage spec.
|
||||
bool isInExternCXXContext() const;
|
||||
|
||||
/// \brief Determines whether this is a global function.
|
||||
bool isGlobal() const;
|
||||
|
||||
|
|
|
@ -1096,14 +1096,6 @@ public:
|
|||
/// C++0x scoped enums), and C++ linkage specifications.
|
||||
bool isTransparentContext() const;
|
||||
|
||||
/// \brief Determines whether this context is, or is nested within,
|
||||
/// a C++ extern "C" linkage spec.
|
||||
bool isExternCContext() const;
|
||||
|
||||
/// \brief Determines whether this context is, or is nested within,
|
||||
/// a C++ extern "C++" linkage spec.
|
||||
bool isExternCXXContext() const;
|
||||
|
||||
/// \brief Determine whether this declaration context is equivalent
|
||||
/// to the declaration context DC.
|
||||
bool Equals(const DeclContext *DC) const {
|
||||
|
|
|
@ -471,9 +471,9 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) {
|
|||
FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
|
||||
}
|
||||
|
||||
template <typename T> static bool isInExternCContext(T *D) {
|
||||
template <typename T> static bool isFirstInExternCContext(T *D) {
|
||||
const T *First = D->getFirstDeclaration();
|
||||
return First->getDeclContext()->isExternCContext();
|
||||
return First->isInExternCContext();
|
||||
}
|
||||
|
||||
static bool isSingleLineExternC(const Decl &D) {
|
||||
|
@ -548,8 +548,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|||
if (D->isInAnonymousNamespace()) {
|
||||
const VarDecl *Var = dyn_cast<VarDecl>(D);
|
||||
const FunctionDecl *Func = dyn_cast<FunctionDecl>(D);
|
||||
if ((!Var || !isInExternCContext(Var)) &&
|
||||
(!Func || !isInExternCContext(Func)))
|
||||
if ((!Var || !isFirstInExternCContext(Var)) &&
|
||||
(!Func || !isFirstInExternCContext(Func)))
|
||||
return LinkageInfo::uniqueExternal();
|
||||
}
|
||||
|
||||
|
@ -626,7 +626,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|||
//
|
||||
// Note that we don't want to make the variable non-external
|
||||
// because of this, but unique-external linkage suits us.
|
||||
if (Context.getLangOpts().CPlusPlus && !isInExternCContext(Var)) {
|
||||
if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) {
|
||||
LinkageInfo TypeLV = Var->getType()->getLinkageAndVisibility();
|
||||
if (TypeLV.getLinkage() != ExternalLinkage)
|
||||
return LinkageInfo::uniqueExternal();
|
||||
|
@ -660,7 +660,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|||
// this translation unit. However, we should use the C linkage
|
||||
// rules instead for extern "C" declarations.
|
||||
if (Context.getLangOpts().CPlusPlus &&
|
||||
!Function->getDeclContext()->isExternCContext() &&
|
||||
!Function->isInExternCContext() &&
|
||||
Function->getType()->getLinkage() == UniqueExternalLinkage)
|
||||
return LinkageInfo::uniqueExternal();
|
||||
|
||||
|
@ -997,7 +997,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
|
|||
LVComputationKind computation) {
|
||||
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
|
||||
if (Function->isInAnonymousNamespace() &&
|
||||
!Function->getDeclContext()->isExternCContext())
|
||||
!Function->isInExternCContext())
|
||||
return LinkageInfo::uniqueExternal();
|
||||
|
||||
// This is a "void f();" which got merged with a file static.
|
||||
|
@ -1020,8 +1020,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
|
|||
|
||||
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
|
||||
if (Var->hasExternalStorage()) {
|
||||
if (Var->isInAnonymousNamespace() &&
|
||||
!Var->getDeclContext()->isExternCContext())
|
||||
if (Var->isInAnonymousNamespace() && !Var->isInExternCContext())
|
||||
return LinkageInfo::uniqueExternal();
|
||||
|
||||
LinkageInfo LV;
|
||||
|
@ -1522,8 +1521,7 @@ static LanguageLinkage getLanguageLinkageTemplate(const T &D) {
|
|||
// If the first decl is in an extern "C" context, any other redeclaration
|
||||
// will have C language linkage. If the first one is not in an extern "C"
|
||||
// context, we would have reported an error for any other decl being in one.
|
||||
const T *First = D.getFirstDeclaration();
|
||||
if (First->getDeclContext()->isExternCContext())
|
||||
if (isFirstInExternCContext(&D))
|
||||
return CLanguageLinkage;
|
||||
return CXXLanguageLinkage;
|
||||
}
|
||||
|
@ -1549,6 +1547,29 @@ bool VarDecl::isExternC() const {
|
|||
return isExternCTemplate(*this);
|
||||
}
|
||||
|
||||
static bool isLinkageSpecContext(const DeclContext *DC,
|
||||
LinkageSpecDecl::LanguageIDs ID) {
|
||||
while (DC->getDeclKind() != Decl::TranslationUnit) {
|
||||
if (DC->getDeclKind() == Decl::LinkageSpec)
|
||||
return cast<LinkageSpecDecl>(DC)->getLanguage() == ID;
|
||||
DC = DC->getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool isInLanguageSpecContext(T *D, LinkageSpecDecl::LanguageIDs ID) {
|
||||
return isLinkageSpecContext(D->getLexicalDeclContext(), ID);
|
||||
}
|
||||
|
||||
bool VarDecl::isInExternCContext() const {
|
||||
return isInLanguageSpecContext(this, LinkageSpecDecl::lang_c);
|
||||
}
|
||||
|
||||
bool VarDecl::isInExternCXXContext() const {
|
||||
return isInLanguageSpecContext(this, LinkageSpecDecl::lang_cxx);
|
||||
}
|
||||
|
||||
VarDecl *VarDecl::getCanonicalDecl() {
|
||||
return getFirstDeclaration();
|
||||
}
|
||||
|
@ -2070,6 +2091,14 @@ bool FunctionDecl::isExternC() const {
|
|||
return isExternCTemplate(*this);
|
||||
}
|
||||
|
||||
bool FunctionDecl::isInExternCContext() const {
|
||||
return isInLanguageSpecContext(this, LinkageSpecDecl::lang_c);
|
||||
}
|
||||
|
||||
bool FunctionDecl::isInExternCXXContext() const {
|
||||
return isInLanguageSpecContext(this, LinkageSpecDecl::lang_cxx);
|
||||
}
|
||||
|
||||
bool FunctionDecl::isGlobal() const {
|
||||
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
|
||||
return Method->isStatic();
|
||||
|
|
|
@ -819,28 +819,6 @@ bool DeclContext::isTransparentContext() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DeclContext::isExternCContext() const {
|
||||
const DeclContext *DC = this;
|
||||
while (DC->DeclKind != Decl::TranslationUnit) {
|
||||
if (DC->DeclKind == Decl::LinkageSpec)
|
||||
return cast<LinkageSpecDecl>(DC)->getLanguage()
|
||||
== LinkageSpecDecl::lang_c;
|
||||
DC = DC->getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeclContext::isExternCXXContext() const {
|
||||
const DeclContext *DC = this;
|
||||
while (DC->DeclKind != Decl::TranslationUnit) {
|
||||
if (DC->DeclKind == Decl::LinkageSpec)
|
||||
return cast<LinkageSpecDecl>(DC)->getLanguage()
|
||||
== LinkageSpecDecl::lang_cxx;
|
||||
DC = DC->getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeclContext::Encloses(const DeclContext *DC) const {
|
||||
if (getPrimaryContext() != this)
|
||||
return getPrimaryContext()->Encloses(DC);
|
||||
|
|
|
@ -1731,8 +1731,8 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
|
|||
|
||||
// Must be in an extern "C" context. Entities declared directly within
|
||||
// a record are not extern "C" even if the record is in such a context.
|
||||
const DeclContext *DC = D->getFirstDeclaration()->getDeclContext();
|
||||
if (DC->isRecord() || !DC->isExternCContext())
|
||||
const SomeDecl *First = D->getFirstDeclaration();
|
||||
if (First->getDeclContext()->isRecord() || !First->isInExternCContext())
|
||||
return;
|
||||
|
||||
// OK, this is an internal linkage entity inside an extern "C" linkage
|
||||
|
|
|
@ -2246,11 +2246,9 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
|
|||
return false;
|
||||
|
||||
LanguageLinkage OldLinkage = Old->getLanguageLinkage();
|
||||
if (OldLinkage == CXXLanguageLinkage &&
|
||||
New->getLexicalDeclContext()->isExternCContext())
|
||||
if (OldLinkage == CXXLanguageLinkage && New->isInExternCContext())
|
||||
return true;
|
||||
if (OldLinkage == CLanguageLinkage &&
|
||||
New->getLexicalDeclContext()->isExternCXXContext())
|
||||
if (OldLinkage == CLanguageLinkage && New->isInExternCXXContext())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -5153,7 +5151,7 @@ static bool mayConflictWithNonVisibleExternC(const T *ND) {
|
|||
// This code runs before the init of foo is set, and therefore before
|
||||
// the type of foo is known. Not knowing the type we cannot know its linkage
|
||||
// unless it is in an extern C block.
|
||||
if (!DC->isExternCContext()) {
|
||||
if (!ND->isInExternCContext()) {
|
||||
const ASTContext &Context = ND->getASTContext();
|
||||
if (Context.getLangOpts().CPlusPlus)
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue