summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/Decl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-12-09 16:59:22 +0000
committerDouglas Gregor <dgregor@apple.com>2010-12-09 16:59:22 +0000
commitff76cb9727f016a580c45e7e6f86bc763d80b337 (patch)
tree9f5f2a7a5d11ce37d7ee23ab5221c2eb5c2cbd61 /clang/lib/AST/Decl.cpp
parentb5e52df6ddfe7662cfe9ddf9503e639ccf7d4405 (diff)
downloadbcm5719-llvm-ff76cb9727f016a580c45e7e6f86bc763d80b337.tar.gz
bcm5719-llvm-ff76cb9727f016a580c45e7e6f86bc763d80b337.zip
When an "inline" declaration was followed by a definition not marked
"inline", we weren't giving the definition weak linkage because the "inline" bit wasn't propagated. This was a longstanding FIXME that, somehow, hadn't triggered a bug in the wild. Fix this problem by tracking whether any declaration was marked "inline", and clean up the semantics of GNU's "extern inline" semantics calculation based on this change. Fixes <rdar://problem/8740363>. llvm-svn: 121373
Diffstat (limited to 'clang/lib/AST/Decl.cpp')
-rw-r--r--clang/lib/AST/Decl.cpp37
1 files changed, 18 insertions, 19 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 1861c8c9b60..d59fc7a344f 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1304,6 +1304,9 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
FunTmpl->setPreviousDeclaration(PrevFunTmpl);
}
+
+ if (PrevDecl->IsInline)
+ IsInline = true;
}
const FunctionDecl *FunctionDecl::getCanonicalDecl() const {
@@ -1410,14 +1413,7 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
}
bool FunctionDecl::isInlined() const {
- // FIXME: This is not enough. Consider:
- //
- // inline void f();
- // void f() { }
- //
- // f is inlined, but does not have inline specified.
- // To fix this we should add an 'inline' flag to FunctionDecl.
- if (isInlineSpecified())
+ if (IsInline)
return true;
if (isa<CXXMethodDecl>(this)) {
@@ -1471,20 +1467,22 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
ASTContext &Context = getASTContext();
if (!Context.getLangOptions().C99 || hasAttr<GNUInlineAttr>()) {
- // GNU inline semantics. Based on a number of examples, we came up with the
- // following heuristic: if the "inline" keyword is present on a
- // declaration of the function but "extern" is not present on that
- // declaration, then the symbol is externally visible. Otherwise, the GNU
- // "extern inline" semantics applies and the symbol is not externally
- // visible.
+ // If it's not the case that both 'inline' and 'extern' are
+ // specified on the definition, then this inline definition is
+ // externally visible.
+ if (!(isInlineSpecified() && getStorageClassAsWritten() == SC_Extern))
+ return true;
+
+ // If any declaration is 'inline' but not 'extern', then this definition
+ // is externally visible.
for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end();
Redecl != RedeclEnd;
++Redecl) {
- if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != SC_Extern)
+ if (Redecl->isInlineSpecified() &&
+ Redecl->getStorageClassAsWritten() != SC_Extern)
return true;
- }
+ }
- // GNU "extern inline" semantics; no externally visible symbol.
return false;
}
@@ -2058,9 +2056,10 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten,
- bool isInline, bool hasWrittenPrototype) {
+ bool isInlineSpecified,
+ bool hasWrittenPrototype) {
FunctionDecl *New = new (C) FunctionDecl(Function, DC, NameInfo, T, TInfo,
- S, SCAsWritten, isInline);
+ S, SCAsWritten, isInlineSpecified);
New->HasWrittenPrototype = hasWrittenPrototype;
return New;
}
OpenPOWER on IntegriCloud