def err_redefinition_extern_inline : Error<
"redefinition of a 'extern inline' function %0 is not supported in "
"%select{C99 mode|C++}1">;
+
+// This should eventually be an error.
+def warn_undefined_internal : Warning<
+ "%select{function|variable}0 %q1 has internal linkage but is not defined">;
+def note_used_here : Note<"used here">;
def warn_redefinition_of_typedef : Warning<
"redefinition of typedef %0 is invalid in C">,
// argument locations.
llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
+ /// UndefinedInternals - all the used, undefined objects with
+ /// internal linkage in this translation unit.
+ llvm::DenseMap<NamedDecl*, SourceLocation> UndefinedInternals;
+
typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
if (const CXXRecordDecl *record = dyn_cast<CXXRecordDecl>(this))
clearLinkageForClass(record);
- if (const ClassTemplateDecl *temp = dyn_cast<ClassTemplateDecl>(this)) {
+ if (ClassTemplateDecl *temp =
+ dyn_cast<ClassTemplateDecl>(const_cast<NamedDecl*>(this))) {
// Clear linkage for the template pattern.
CXXRecordDecl *record = temp->getTemplatedDecl();
record->HasCachedLinkage = 0;
clearLinkageForClass(record);
- // ...do we need to clear linkage for specializations, too?
+ // We need to clear linkage for specializations, too.
+ for (ClassTemplateDecl::spec_iterator
+ i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i)
+ i->ClearLinkageCache();
}
+
+ // Clear cached linkage for function template decls, too.
+ if (FunctionTemplateDecl *temp =
+ dyn_cast<FunctionTemplateDecl>(const_cast<NamedDecl*>(this)))
+ for (FunctionTemplateDecl::spec_iterator
+ i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i)
+ i->ClearLinkageCache();
+
}
Linkage NamedDecl::getLinkage() const {
// Set linkage and visibility in case we never see a definition.
NamedDecl::LinkageInfo LV = D->getLinkageAndVisibility();
if (LV.linkage() != ExternalLinkage) {
- GV->setLinkage(llvm::GlobalValue::InternalLinkage);
+ // Don't set internal linkage on declarations.
} else {
if (D->hasAttr<DLLImportAttr>())
GV->setLinkage(llvm::GlobalValue::DLLImportLinkage);
return false;
}
+namespace {
+ struct UndefinedInternal {
+ NamedDecl *decl;
+ FullSourceLoc useLoc;
+
+ UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc)
+ : decl(decl), useLoc(useLoc) {}
+ };
+
+ bool operator<(const UndefinedInternal &l, const UndefinedInternal &r) {
+ return l.useLoc.isBeforeInTranslationUnitThan(r.useLoc);
+ }
+}
+
+/// checkUndefinedInternals - Check for undefined objects with internal linkage.
+static void checkUndefinedInternals(Sema &S) {
+ if (S.UndefinedInternals.empty()) return;
+
+ // Collect all the still-undefined entities with internal linkage.
+ llvm::SmallVector<UndefinedInternal, 16> undefined;
+ for (llvm::DenseMap<NamedDecl*,SourceLocation>::iterator
+ i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end();
+ i != e; ++i) {
+ NamedDecl *decl = i->first;
+
+ // Ignore attributes that have become invalid.
+ if (decl->isInvalidDecl()) continue;
+
+ // __attribute__((weakref)) is basically a definition.
+ if (decl->hasAttr<WeakRefAttr>()) continue;
+
+ if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+ if (fn->isPure() || fn->hasBody())
+ continue;
+ } else {
+ if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly)
+ continue;
+ }
+
+ // We build a FullSourceLoc so that we can sort with array_pod_sort.
+ FullSourceLoc loc(i->second, S.Context.getSourceManager());
+ undefined.push_back(UndefinedInternal(decl, loc));
+ }
+
+ if (undefined.empty()) return;
+
+ // Sort (in order of use site) so that we're not (as) dependent on
+ // the iteration order through an llvm::DenseMap.
+ llvm::array_pod_sort(undefined.begin(), undefined.end());
+
+ for (llvm::SmallVectorImpl<UndefinedInternal>::iterator
+ i = undefined.begin(), e = undefined.end(); i != e; ++i) {
+ NamedDecl *decl = i->decl;
+ S.Diag(decl->getLocation(), diag::warn_undefined_internal)
+ << isa<VarDecl>(decl) << decl;
+ S.Diag(i->useLoc, diag::note_used_here);
+ }
+}
+
/// ActOnEndOfTranslationUnit - This is called at the very end of the
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
<< DiagD->getDeclName();
}
}
+
+ checkUndefinedInternals(*this);
}
TUScope = 0;
MarkVTableUsed(Loc, MethodDecl->getParent());
}
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ // Recursive functions should be marked when used from another function.
+ if (CurContext == Function) return;
+
// Implicit instantiation of function templates and member functions of
// class templates.
if (Function->isImplicitlyInstantiable()) {
else
PendingInstantiations.push_back(std::make_pair(Function, Loc));
}
- } else // Walk redefinitions, as some of them may be instantiable.
+ } else {
+ // Walk redefinitions, as some of them may be instantiable.
for (FunctionDecl::redecl_iterator i(Function->redecls_begin()),
e(Function->redecls_end()); i != e; ++i) {
if (!i->isUsed(false) && i->isImplicitlyInstantiable())
MarkDeclarationReferenced(Loc, *i);
}
+ }
- // FIXME: keep track of references to static functions
-
- // Recursive functions should be marked when used from another function.
- if (CurContext != Function)
- Function->setUsed(true);
+ // Keep track of used but undefined functions.
+ if (!Function->isPure() && !Function->hasBody() &&
+ Function->getLinkage() != ExternalLinkage) {
+ SourceLocation &old = UndefinedInternals[Function->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
+ }
+ Function->setUsed(true);
return;
}
}
}
- // FIXME: keep track of references to static data?
+ // Keep track of used but undefined variables.
+ if (Var->hasDefinition() == VarDecl::DeclarationOnly
+ && Var->getLinkage() != ExternalLinkage) {
+ SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
+ }
D->setUsed(true);
return;
struct A { };
struct B {
- operator A();
+ operator A() { return A(); }
};
A f(char *dst) {
typedef const struct __CFDictionary * CFDictionaryRef;
extern Boolean CFDictionaryGetValueIfPresent(CFDictionaryRef theDict, const void *key, const void **value);
-static void shazam(NSUInteger i, unsigned char **out);
+void shazam(NSUInteger i, unsigned char **out);
void rdar_6440393_1(NSDictionary *dict) {
NSInteger x = 0;
typedef void (*FType)(int, int) __attribute ((regparm (3), stdcall));
FType bar;
-static void FASTCALL
-reduced(char b, double c, foo* d, double e, int f);
+extern void FASTCALL reduced(char b, double c, foo* d, double e, int f);
// PR7025
void FASTCALL f1(int i, int j, int k);
// PR3442
-static void *g(unsigned long len);
+void *g(unsigned long len);
void
f(int n)
Twine(const char *Str) { }
};
-static void error(const Twine &Message);
+static void error(const Twine &Message) {}
template<typename>
struct opt_storage {
// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
struct Global { Global(); };
-template<typename T> struct X { X(); };
+template<typename T> struct X { X() {} };
namespace {
- struct Anon { Anon(); };
+ struct Anon { Anon() {} };
// CHECK: @_ZN12_GLOBAL__N_15anon0E = internal global
Global anon0;
namespace {
struct testg { virtual void a(); };
}
+void testg::a() {}
testg *testgvar = new testg;
struct X0 { virtual ~X0(); };
}
// Check that the thunk gets internal linkage.
-namespace {
-
-struct A {
- virtual void f();
-};
-
-struct B {
- virtual void f();
-};
-
-struct C : A, B {
- virtual void c();
-
- virtual void f();
-};
+namespace Test4B {
+ struct A {
+ virtual void f();
+ };
-void C::f() { }
+ struct B {
+ virtual void f();
+ };
-}
+ namespace {
+ struct C : A, B {
+ virtual void c();
+ virtual void f();
+ };
+ }
+ void C::c() {}
+ void C::f() {}
-// Force C::f to be used.
-void f() {
- C c;
-
- c.f();
+ // Force C::f to be used.
+ void f() {
+ C c;
+ c.f();
+ }
}
namespace Test5 {
// This is from Test5:
// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
-// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv(
+// CHECK: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
@implementation Bar
-static int func(int i);
+static int func(int i) { return 0; }
- (void)baz {
Foo *obj1, *obj2;
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Make sure we don't produce invalid IR.
+// RUN: %clang_cc1 -emit-llvm-only %s
+
+namespace test1 {
+ static void foo(); // expected-warning {{function 'test1::foo' has internal linkage but is not defined}}
+ template <class T> static void bar(); // expected-warning {{function 'test1::bar<int>' has internal linkage but is not defined}}
+
+ void test() {
+ foo(); // expected-note {{used here}}
+ bar<int>(); // expected-note {{used here}}
+ }
+}
+
+namespace test2 {
+ namespace {
+ void foo(); // expected-warning {{function 'test2::<anonymous namespace>::foo' has internal linkage but is not defined}}
+ extern int var; // expected-warning {{variable 'test2::<anonymous namespace>::var' has internal linkage but is not defined}}
+ template <class T> void bar(); // expected-warning {{function 'test2::<anonymous namespace>::bar<int>' has internal linkage but is not defined}}
+ }
+ void test() {
+ foo(); // expected-note {{used here}}
+ var = 0; // expected-note {{used here}}
+ bar<int>(); // expected-note {{used here}}
+ }
+}
+
+namespace test3 {
+ namespace {
+ void foo();
+ extern int var;
+ template <class T> void bar();
+ }
+
+ void test() {
+ foo();
+ var = 0;
+ bar<int>();
+ }
+
+ namespace {
+ void foo() {}
+ int var = 0;
+ template <class T> void bar() {}
+ }
+}
+
+namespace test4 {
+ namespace {
+ struct A {
+ A(); // expected-warning {{function 'test4::<anonymous namespace>::A::A' has internal linkage but is not defined}}
+ ~A();// expected-warning {{function 'test4::<anonymous namespace>::A::~A' has internal linkage but is not defined}}
+ virtual void foo(); // expected-warning {{function 'test4::<anonymous namespace>::A::foo' has internal linkage but is not defined}}
+ virtual void bar() = 0;
+ virtual void baz(); // expected-warning {{function 'test4::<anonymous namespace>::A::baz' has internal linkage but is not defined}}
+ };
+ }
+
+ void test(A &a) {
+ a.foo(); // expected-note {{used here}}
+ a.bar();
+ a.baz(); // expected-note {{used here}}
+ }
+
+ struct Test : A {
+ Test() {} // expected-note 2 {{used here}}
+ };
+}
+
+// rdar://problem/9014651
+namespace test5 {
+ namespace {
+ struct A {};
+ }
+
+ template <class N> struct B {
+ static int var; // expected-warning {{variable 'test5::B<test5::<anonymous>::A>::var' has internal linkage but is not defined}}
+ static void foo(); // expected-warning {{function 'test5::B<test5::<anonymous>::A>::foo' has internal linkage but is not defined}}
+ };
+
+ void test() {
+ B<A>::var = 0; // expected-note {{used here}}
+ B<A>::foo(); // expected-note {{used here}}
+ }
+}