mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
Don't mark 'extern "C" void f(void)' as having extern storage class.
Instead, we check for one line extern "C" context in linkage computation and when deciding if a variable is a definition. This hopefully completes the transition to having "as written" semantics for hasExternalStorage. llvm-svn: 180258
This commit is contained in:
parent
5c38383205
commit
bff5956cfa
@ -1572,17 +1572,20 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(
|
||||
// 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
|
||||
|
@ -3350,10 +3350,16 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
|
||||
/// 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;
|
||||
@ -3551,9 +3557,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
|
||||
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
|
||||
@ -4676,9 +4680,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
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
|
||||
@ -5290,7 +5293,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
|
||||
// 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();
|
||||
@ -5642,7 +5645,10 @@ static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef,
|
||||
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:
|
||||
|
7
clang/test/CXX/dcl.dcl/dcl.link/p7-2.cpp
Normal file
7
clang/test/CXX/dcl.dcl/dcl.link/p7-2.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
// RUN: %clang_cc1 -ast-print -o - %s | FileCheck %s
|
||||
|
||||
extern "C" void f(void);
|
||||
// CHECK: extern "C" void f()
|
||||
|
||||
extern "C" void v;
|
||||
// CHECK: extern "C" void v
|
Loading…
Reference in New Issue
Block a user