// initializer, the declaration is an external definition for the identifier
if (hasInit())
return Definition;
- // AST for 'extern "C" int foo;' is annotated with 'extern'.
+
if (hasExternalStorage())
return DeclarationOnly;
- if (hasExternalStorage()) {
- for (const VarDecl *PrevVar = getPreviousDecl();
- PrevVar; PrevVar = PrevVar->getPreviousDecl()) {
- if (PrevVar->getLinkage() == InternalLinkage)
- return DeclarationOnly;
- }
+ // [dcl.link] p7:
+ // A declaration directly contained in a linkage-specification is treated
+ // as if it contains the extern specifier for the purpose of determining
+ // the linkage of the declared name and whether it is a definition.
+ const DeclContext *DC = getDeclContext();
+ if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(DC)) {
+ if (SD->getLanguage() == LinkageSpecDecl::lang_c && !SD->hasBraces())
+ return DeclarationOnly;
}
+
// C99 6.9.2p2:
// A declaration of an object that has file scope without an initializer,
// and without a storage class specifier or the scs 'static', constitutes
/// a VarDecl::StorageClass. Any error reporting is up to the caller:
/// illegal input values are mapped to SC_None.
static StorageClass
-StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
+StorageClassSpecToVarDeclStorageClass(const DeclSpec &DS) {
+ DeclSpec::SCS StorageClassSpec = DS.getStorageClassSpec();
+ assert(StorageClassSpec != DeclSpec::SCS_typedef &&
+ "Parser allowed 'typedef' as storage class VarDecl.");
switch (StorageClassSpec) {
case DeclSpec::SCS_unspecified: return SC_None;
- case DeclSpec::SCS_extern: return SC_Extern;
+ case DeclSpec::SCS_extern:
+ if (DS.isExternInLinkageSpec())
+ return SC_None;
+ return SC_Extern;
case DeclSpec::SCS_static: return SC_Static;
case DeclSpec::SCS_auto: return SC_Auto;
case DeclSpec::SCS_register: return SC_Register;
FieldCollector->Add(cast<FieldDecl>(Anon));
} else {
DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
- assert(SCSpec != DeclSpec::SCS_typedef &&
- "Parser allowed 'typedef' as storage class VarDecl.");
- VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+ VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(DS);
if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
DeclarationName Name = GetNameForDeclarator(D).getName();
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
- assert(SCSpec != DeclSpec::SCS_typedef &&
- "Parser allowed 'typedef' as storage class VarDecl.");
- VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+ VarDecl::StorageClass SC =
+ StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16) {
// OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
// Filter out any non-conflicting previous declarations.
filterNonConflictingPreviousDecls(Context, NewVD, Previous);
- if (T->isVoidType() && !NewVD->hasExternalStorage()) {
+ if (T->isVoidType() && NewVD->isThisDeclarationADefinition()) {
Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
<< T;
NewVD->setInvalidDecl();
D.setInvalidType();
break;
case DeclSpec::SCS_unspecified: break;
- case DeclSpec::SCS_extern: return SC_Extern;
+ case DeclSpec::SCS_extern:
+ if (D.getDeclSpec().isExternInLinkageSpec())
+ return SC_None;
+ return SC_Extern;
case DeclSpec::SCS_static: {
if (SemaRef.CurContext->getRedeclContext()->isFunctionOrMethod()) {
// C99 6.7.1p5: