Fixed typedef inside extern "C".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109865 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index d2cd744..c507227 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -219,8 +219,15 @@
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 @@
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::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,