diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-09-20 07:22:00 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-09-20 07:22:00 +0000 |
commit | 4e8386f480e758e0e5e9c26c7439ac7bf9a71d23 (patch) | |
tree | 6fcb3c4875d5c2ec71f89351ee84dc87c16d2d52 /include/clang | |
parent | 8385a295e2d9a3f7ea56000826056d669d562dab (diff) | |
download | clang-4e8386f480e758e0e5e9c26c7439ac7bf9a71d23.tar.gz |
Implement C++ [basic.link]p8.
If a function or variable has a type with no linkage (and is not extern "C"),
any use of it requires a definition within the same translation unit; the idea
is that it is not possible to define the entity elsewhere, so any such use is
necessarily an error.
There is an exception, though: some types formally have no linkage but
nonetheless can be referenced from other translation units (for example, this
happens to anonymous structures defined within inline functions). For entities
with those types, we suppress the diagnostic except under -pedantic.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313729 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 8 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 5 | ||||
-rw-r--r-- | include/clang/Sema/SemaInternal.h | 3 |
3 files changed, 15 insertions, 1 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 3974fe0eea..16fee89130 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4707,6 +4707,14 @@ def note_deleted_assign_field : Note< def warn_undefined_internal : Warning< "%select{function|variable}0 %q1 has internal linkage but is not defined">, InGroup<DiagGroup<"undefined-internal">>; +def err_undefined_internal_type : Error< + "%select{function|variable}0 %q1 is used but not defined in this " + "translation unit, and cannot be defined in any other translation unit " + "because its type does not have linkage">; +def ext_undefined_internal_type : Extension< + "ISO C++ requires a definition in this translation unit for " + "%select{function|variable}0 %q1 because its type does not have linkage">, + InGroup<DiagGroup<"undefined-internal-type">>; def warn_undefined_inline : Warning<"inline function %q0 is not defined">, InGroup<DiagGroup<"undefined-inline">>; def err_undefined_inline_var : Error<"inline variable %q0 is not defined">; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index fc34f6816f..9420407acb 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1086,6 +1086,11 @@ public: /// definition in this translation unit. llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed; + /// Determine if VD, which must be a variable or function, is an external + /// symbol that nonetheless can't be referenced from outside this translation + /// unit because its type has no linkage and it's not extern "C". + bool isExternalWithNoLinkageType(ValueDecl *VD); + /// Obtain a sorted list of functions that are undefined but ODR-used. void getUndefinedButUsed( SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined); diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h index a01e8d639f..4dc215ba21 100644 --- a/include/clang/Sema/SemaInternal.h +++ b/include/clang/Sema/SemaInternal.h @@ -73,7 +73,8 @@ inline void MarkVarDeclODRUsed(VarDecl *Var, // Keep track of used but undefined variables. // FIXME: We shouldn't suppress this warning for static data members. if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly && - (!Var->isExternallyVisible() || Var->isInline()) && + (!Var->isExternallyVisible() || Var->isInline() || + SemaRef.isExternalWithNoLinkageType(Var)) && !(Var->isStaticDataMember() && Var->hasInit())) { SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()]; if (old.isInvalid()) |