aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/DeclSpec.cpp
diff options
context:
space:
mode:
authorAbramo Bagnara <abramo.bagnara@gmail.com>2010-07-30 16:47:02 +0000
committerAbramo Bagnara <abramo.bagnara@gmail.com>2010-07-30 16:47:02 +0000
commit35f9a196ef897b9559de25aaecd957208f0b4f59 (patch)
tree40ed53f154273d6c26af74c1ed72c5cb19c83ec4 /lib/Parse/DeclSpec.cpp
parentacc9bf3716be80a19f514f228cb903c0910a1725 (diff)
Fixed typedef inside extern "C".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109865 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/DeclSpec.cpp')
-rw-r--r--lib/Parse/DeclSpec.cpp21
1 files changed, 18 insertions, 3 deletions
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index d2cd74418a..c5072276bc 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/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,