aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/Decl.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-02-14 01:18:37 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-02-14 01:18:37 +0000
commit950fee2555f7a6bd193e588d6b6a941fd182391a (patch)
treea0dd9afcad02780d91902e9510ea41187947662d /lib/AST/Decl.cpp
parentd3b4f0e27ffa8d73f8c69a717c39c39a4d47ff0c (diff)
Add a getLanguageLinkage method to VarDecls and FunctionDecls. Use it to fix
some cases where functions with no language linkage were being treated as having C language linkage. In particular, don't warn in extern "C" { static NonPod foo(); } Since getLanguageLinkage checks the language linkage, the linkage computation cannot use the language linkage. Break the loop by checking just the context in the linkage computation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175117 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r--lib/AST/Decl.cpp35
1 files changed, 24 insertions, 11 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d6778ecf39..5c489273d2 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -196,6 +196,12 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) {
FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
}
+template<typename T>
+bool isInExternCContext(T *D) {
+ const T *First = D->getFirstDeclaration();
+ return First->getDeclContext()->isExternCContext();
+}
+
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
bool OnlyTemplate) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
@@ -262,8 +268,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 || !Var->hasCLanguageLinkage()) &&
- (!Func || !Func->hasCLanguageLinkage()))
+ if ((!Var || !isInExternCContext(Var)) &&
+ (!Func || !isInExternCContext(Func)))
return LinkageInfo::uniqueExternal();
}
@@ -1210,29 +1216,36 @@ SourceRange VarDecl::getSourceRange() const {
}
template<typename T>
-static bool hasCLanguageLinkageTemplate(const T &D) {
+static LanguageLinkage getLanguageLinkageTemplate(const T &D) {
// Language linkage is a C++ concept, but saying that everything in C has
// C language linkage fits the implementation nicely.
ASTContext &Context = D.getASTContext();
if (!Context.getLangOpts().CPlusPlus)
- return true;
+ return CLanguageLinkage;
+
+ // dcl.link 1: All function types, function names with external linkage, and
+ // variable names with external linkage have a language linkage.
+ if (!isExternalLinkage(D.getLinkage()))
+ return NoLanguageLinkage;
// dcl.link 4: A C language linkage is ignored in determining the language
// linkage of the names of class members and the function type of class member
// functions.
const DeclContext *DC = D.getDeclContext();
if (DC->isRecord())
- return false;
+ return CXXLanguageLinkage;
// 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();
- return First->getDeclContext()->isExternCContext();
+ if (First->getDeclContext()->isExternCContext())
+ return CLanguageLinkage;
+ return CXXLanguageLinkage;
}
-bool VarDecl::hasCLanguageLinkage() const {
- return hasCLanguageLinkageTemplate(*this);
+LanguageLinkage VarDecl::getLanguageLinkage() const {
+ return getLanguageLinkageTemplate(*this);
}
bool VarDecl::isExternC() const {
@@ -1757,14 +1770,14 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const {
return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy);
}
-bool FunctionDecl::hasCLanguageLinkage() const {
+LanguageLinkage FunctionDecl::getLanguageLinkage() const {
// Users expect to be able to write
// extern "C" void *__builtin_alloca (size_t);
// so consider builtins as having C language linkage.
if (getBuiltinID())
- return true;
+ return CLanguageLinkage;
- return hasCLanguageLinkageTemplate(*this);
+ return getLanguageLinkageTemplate(*this);
}
bool FunctionDecl::isExternC() const {