summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-05-05 20:15:21 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-05-05 20:15:21 +0000
commitd8ffd0b7b61566f15a67192883a607f7703bcece (patch)
tree1589b51840a6db685aa0913ea7c019eef0f47e36
parent287f24d3991994b9a263af9e2a873f4feadfb8fa (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181165 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Decl.h16
-rw-r--r--include/clang/AST/DeclBase.h8
-rw-r--r--lib/AST/Decl.cpp51
-rw-r--r--lib/AST/DeclBase.cpp22
-rw-r--r--lib/CodeGen/CodeGenModule.cpp4
-rw-r--r--lib/Sema/SemaDecl.cpp8
6 files changed, 61 insertions, 48 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index d0bf559d1e..a0c76c069b 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -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;
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index a4a52e2a78..754facfb59 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -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 {
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index ff012fc401..ab9d73b917 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -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();
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 7b7900640b..084a4321d8 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -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);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 6ebd1d1410..ff183c96e0 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -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
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b5e2c6ebe8..8f78ead59e 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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;