diff options
author | Abramo Bagnara <abramo.bagnara@gmail.com> | 2010-07-30 16:47:02 +0000 |
---|---|---|
committer | Abramo Bagnara <abramo.bagnara@gmail.com> | 2010-07-30 16:47:02 +0000 |
commit | ed5b6899ab52ec19721b6432cc6c33dca48ebd24 (patch) | |
tree | 618a3eb3b179e83acdac9bb76b06cc7b05a01dcb /clang/lib/Parse/DeclSpec.cpp | |
parent | 14eb7bd76914f57c3dd6e375b58b5d7d4e3d844f (diff) | |
download | bcm5719-llvm-ed5b6899ab52ec19721b6432cc6c33dca48ebd24.tar.gz bcm5719-llvm-ed5b6899ab52ec19721b6432cc6c33dca48ebd24.zip |
Fixed typedef inside extern "C".
llvm-svn: 109865
Diffstat (limited to 'clang/lib/Parse/DeclSpec.cpp')
-rw-r--r-- | clang/lib/Parse/DeclSpec.cpp | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/clang/lib/Parse/DeclSpec.cpp b/clang/lib/Parse/DeclSpec.cpp index d2cd74418af..c5072276bc1 100644 --- a/clang/lib/Parse/DeclSpec.cpp +++ b/clang/lib/Parse/DeclSpec.cpp @@ -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, |