forked from OSchip/llvm-project
parent
14eb7bd769
commit
ed5b6899ab
|
@ -162,6 +162,7 @@ private:
|
|||
// storage-class-specifier
|
||||
/*SCS*/unsigned StorageClassSpec : 3;
|
||||
bool SCS_thread_specified : 1;
|
||||
bool SCS_extern_in_linkage_spec : 1;
|
||||
|
||||
// type-specifier
|
||||
/*TSW*/unsigned TypeSpecWidth : 2;
|
||||
|
@ -221,9 +222,7 @@ private:
|
|||
|
||||
WrittenBuiltinSpecs writtenBS;
|
||||
void SaveWrittenBuiltinSpecs();
|
||||
void SaveStorageSpecifierAsWritten() {
|
||||
StorageClassSpecAsWritten = StorageClassSpec;
|
||||
}
|
||||
void SaveStorageSpecifierAsWritten();
|
||||
|
||||
DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT
|
||||
void operator=(const DeclSpec&); // DO NOT IMPLEMENT
|
||||
|
@ -232,6 +231,7 @@ public:
|
|||
DeclSpec()
|
||||
: StorageClassSpec(SCS_unspecified),
|
||||
SCS_thread_specified(false),
|
||||
SCS_extern_in_linkage_spec(false),
|
||||
TypeSpecWidth(TSW_unspecified),
|
||||
TypeSpecComplex(TSC_unspecified),
|
||||
TypeSpecSign(TSS_unspecified),
|
||||
|
@ -262,6 +262,10 @@ public:
|
|||
// storage-class-specifier
|
||||
SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
|
||||
bool isThreadSpecified() const { return SCS_thread_specified; }
|
||||
bool isExternInLinkageSpec() const { return SCS_extern_in_linkage_spec; }
|
||||
void setExternInLinkageSpec(bool Value) {
|
||||
SCS_extern_in_linkage_spec = Value;
|
||||
}
|
||||
|
||||
SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
|
||||
SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
|
||||
|
@ -269,6 +273,7 @@ public:
|
|||
void ClearStorageClassSpecs() {
|
||||
StorageClassSpec = DeclSpec::SCS_unspecified;
|
||||
SCS_thread_specified = false;
|
||||
SCS_extern_in_linkage_spec = false;
|
||||
StorageClassSpecLoc = SourceLocation();
|
||||
SCS_threadLoc = SourceLocation();
|
||||
}
|
||||
|
|
|
@ -219,8 +219,15 @@ const char *DeclSpec::getSpecifierName(TQ T) {
|
|||
bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
|
||||
const char *&PrevSpec,
|
||||
unsigned &DiagID) {
|
||||
if (StorageClassSpec != SCS_unspecified)
|
||||
return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
|
||||
if (StorageClassSpec != SCS_unspecified) {
|
||||
// Changing storage class is allowed only if the previous one
|
||||
// was the 'extern' that is part of a linkage specification and
|
||||
// the new storage class is 'typedef'.
|
||||
if (!(SCS_extern_in_linkage_spec &&
|
||||
StorageClassSpec == SCS_extern &&
|
||||
S == SCS_typedef))
|
||||
return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
|
||||
}
|
||||
StorageClassSpec = S;
|
||||
StorageClassSpecLoc = Loc;
|
||||
assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield");
|
||||
|
@ -240,7 +247,6 @@ bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// These methods set the specified attribute of the DeclSpec, but return true
|
||||
/// and ignore the request if invalid (e.g. "extern" then "auto" is
|
||||
/// specified).
|
||||
|
@ -430,6 +436,15 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
|
|||
}
|
||||
}
|
||||
|
||||
void DeclSpec::SaveStorageSpecifierAsWritten() {
|
||||
if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern)
|
||||
// If 'extern' is part of a linkage specification,
|
||||
// then it is not a storage class "as written".
|
||||
StorageClassSpecAsWritten = SCS_unspecified;
|
||||
else
|
||||
StorageClassSpecAsWritten = StorageClassSpec;
|
||||
}
|
||||
|
||||
/// Finish - This does final analysis of the declspec, rejecting things like
|
||||
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
|
||||
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
|
||||
|
|
|
@ -196,6 +196,7 @@ Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
|
|||
}
|
||||
|
||||
if (Tok.isNot(tok::l_brace)) {
|
||||
DS.setExternInLinkageSpec(true);
|
||||
ParseDeclarationOrFunctionDefinition(DS, Attr.AttrList);
|
||||
return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
|
||||
SourceLocation());
|
||||
|
|
|
@ -1667,21 +1667,11 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
|
|||
/// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to
|
||||
/// a VarDecl::StorageClass. Any error reporting is up to the caller:
|
||||
/// illegal input values are mapped to VarDecl::None.
|
||||
/// If the input declaration context is a linkage specification
|
||||
/// with no braces, then Extern is mapped to None.
|
||||
static VarDecl::StorageClass
|
||||
StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec,
|
||||
DeclContext *DC) {
|
||||
StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
|
||||
switch (StorageClassSpec) {
|
||||
case DeclSpec::SCS_unspecified: return VarDecl::None;
|
||||
case DeclSpec::SCS_extern:
|
||||
// If the current context is a C++ linkage specification
|
||||
// having no braces, then the keyword "extern" is properly part
|
||||
// of the linkage specification itself, rather than being
|
||||
// the written storage class specifier.
|
||||
return (DC && isa<LinkageSpecDecl>(DC) &&
|
||||
!cast<LinkageSpecDecl>(DC)->hasBraces())
|
||||
? VarDecl::None : VarDecl::Extern;
|
||||
case DeclSpec::SCS_extern: return VarDecl::Extern;
|
||||
case DeclSpec::SCS_static: return VarDecl::Static;
|
||||
case DeclSpec::SCS_auto: return VarDecl::Auto;
|
||||
case DeclSpec::SCS_register: return VarDecl::Register;
|
||||
|
@ -1696,21 +1686,11 @@ StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec,
|
|||
/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to
|
||||
/// a FunctionDecl::StorageClass. Any error reporting is up to the caller:
|
||||
/// illegal input values are mapped to FunctionDecl::None.
|
||||
/// If the input declaration context is a linkage specification
|
||||
/// with no braces, then Extern is mapped to None.
|
||||
static FunctionDecl::StorageClass
|
||||
StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec,
|
||||
DeclContext *DC) {
|
||||
StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
|
||||
switch (StorageClassSpec) {
|
||||
case DeclSpec::SCS_unspecified: return FunctionDecl::None;
|
||||
case DeclSpec::SCS_extern:
|
||||
// If the current context is a C++ linkage specification
|
||||
// having no braces, then the keyword "extern" is properly part
|
||||
// of the linkage specification itself, rather than being
|
||||
// the written storage class specifier.
|
||||
return (DC && isa<LinkageSpecDecl>(DC) &&
|
||||
!cast<LinkageSpecDecl>(DC)->hasBraces())
|
||||
? FunctionDecl::None : FunctionDecl::Extern;
|
||||
case DeclSpec::SCS_extern: return FunctionDecl::Extern;
|
||||
case DeclSpec::SCS_static: return FunctionDecl::Static;
|
||||
case DeclSpec::SCS_private_extern: return FunctionDecl::PrivateExtern;
|
||||
// Illegal SCSs map to None: error reporting is up to the caller.
|
||||
|
@ -1851,7 +1831,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
|
|||
DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
|
||||
assert(SCSpec != DeclSpec::SCS_typedef &&
|
||||
"Parser allowed 'typedef' as storage class VarDecl.");
|
||||
VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec, 0);
|
||||
VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
|
||||
if (SCSpec == DeclSpec::SCS_mutable) {
|
||||
// mutable can only appear on non-static class members, so it's always
|
||||
// an error here
|
||||
|
@ -1861,7 +1841,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
|
|||
}
|
||||
SCSpec = DS.getStorageClassSpecAsWritten();
|
||||
VarDecl::StorageClass SCAsWritten
|
||||
= StorageClassSpecToVarDeclStorageClass(SCSpec, 0);
|
||||
= StorageClassSpecToVarDeclStorageClass(SCSpec);
|
||||
|
||||
Anon = VarDecl::Create(Context, Owner, Record->getLocation(),
|
||||
/*IdentifierInfo=*/0,
|
||||
|
@ -2521,7 +2501,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
|
||||
assert(SCSpec != DeclSpec::SCS_typedef &&
|
||||
"Parser allowed 'typedef' as storage class VarDecl.");
|
||||
VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec, 0);
|
||||
VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
|
||||
if (SCSpec == DeclSpec::SCS_mutable) {
|
||||
// mutable can only appear on non-static class members, so it's always
|
||||
// an error here
|
||||
|
@ -2531,7 +2511,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
}
|
||||
SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
|
||||
VarDecl::StorageClass SCAsWritten
|
||||
= StorageClassSpecToVarDeclStorageClass(SCSpec, DC);
|
||||
= StorageClassSpecToVarDeclStorageClass(SCSpec);
|
||||
|
||||
IdentifierInfo *II = Name.getAsIdentifierInfo();
|
||||
if (!II) {
|
||||
|
@ -3016,7 +2996,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
|
||||
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
|
||||
FunctionDecl::StorageClass SCAsWritten
|
||||
= StorageClassSpecToFunctionDeclStorageClass(SCSpec, DC);
|
||||
= StorageClassSpecToFunctionDeclStorageClass(SCSpec);
|
||||
|
||||
// Check that the return type is not an abstract class type.
|
||||
// For record types, this is done by the AbstractClassUsageDiagnoser once
|
||||
|
|
|
@ -5909,7 +5909,7 @@ Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S,
|
|||
return DeclPtrTy::make(D);
|
||||
}
|
||||
|
||||
/// ActOnFinishLinkageSpecification - Completely the definition of
|
||||
/// ActOnFinishLinkageSpecification - Complete the definition of
|
||||
/// the C++ linkage specification LinkageSpec. If RBraceLoc is
|
||||
/// valid, it's the position of the closing '}' brace in a linkage
|
||||
/// specification that uses braces.
|
||||
|
|
|
@ -54,3 +54,6 @@ extern "C"
|
|||
return f2((char *)0);
|
||||
}
|
||||
}
|
||||
|
||||
// PR6991
|
||||
extern "C" typedef int (*PutcFunc_t)(int);
|
||||
|
|
Loading…
Reference in New Issue