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:
Rafael Espindola 2013-05-05 20:15:21 +00:00
parent 1debc468fa
commit 593537a979
6 changed files with 61 additions and 48 deletions

View File

@ -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;

View File

@ -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 {

View File

@ -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();

View File

@ -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);

View File

@ -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

View File

@ -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;