summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-09-04 19:54:14 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-09-04 19:54:14 +0000
commit58c743370994da37df3c6ebba76a8277af8483e0 (patch)
tree00d4ed51761297f5bc38225ba635184165444a41 /clang/lib/Sema
parente9c4e84f8ea7a8245b1cbb44e158cf0b8d29eb28 (diff)
downloadbcm5719-llvm-58c743370994da37df3c6ebba76a8277af8483e0.tar.gz
bcm5719-llvm-58c743370994da37df3c6ebba76a8277af8483e0.zip
PR10458: Finesse behaviour of C++0x features when in pre-0x mode. Accept for-range and auto with an ExtWarn, and produce a -Wc++0x-compat warning in C++98 mode when auto is used as a storage class.
llvm-svn: 139102
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/DeclSpec.cpp36
1 files changed, 35 insertions, 1 deletions
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index c87f2cff548..c388192bfef 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -425,10 +425,23 @@ bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
}
if (StorageClassSpec != SCS_unspecified) {
+ // Maybe this is an attempt to use C++0x 'auto' outside of C++0x mode.
+ bool isInvalid = true;
+ if (TypeSpecType == TST_unspecified && Lang.CPlusPlus) {
+ if (S == SCS_auto)
+ return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID);
+ if (StorageClassSpec == SCS_auto) {
+ isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc,
+ PrevSpec, DiagID);
+ assert(!isInvalid && "auto SCS -> TST recovery failed");
+ }
+ }
+
// 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 &&
+ if (isInvalid &&
+ !(SCS_extern_in_linkage_spec &&
StorageClassSpec == SCS_extern &&
S == SCS_typedef))
return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
@@ -836,6 +849,27 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
}
}
+ // If no type specifier was provided and we're parsing a language where
+ // the type specifier is not optional, but we got 'auto' as a storage
+ // class specifier, then assume this is an attempt to use C++0x's 'auto'
+ // type specifier.
+ // FIXME: Does Microsoft really support implicit int in C++?
+ if (PP.getLangOptions().CPlusPlus && !PP.getLangOptions().Microsoft &&
+ TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) {
+ TypeSpecType = TST_auto;
+ StorageClassSpec = StorageClassSpecAsWritten = SCS_unspecified;
+ TSTLoc = TSTNameLoc = StorageClassSpecLoc;
+ StorageClassSpecLoc = SourceLocation();
+ }
+ // Diagnose if we've recovered from an ill-formed 'auto' storage class
+ // specifier in a pre-C++0x dialect of C++.
+ if (!PP.getLangOptions().CPlusPlus0x && TypeSpecType == TST_auto)
+ Diag(D, TSTLoc, diag::ext_auto_type_specifier);
+ if (PP.getLangOptions().CPlusPlus && !PP.getLangOptions().CPlusPlus0x &&
+ StorageClassSpec == SCS_auto)
+ Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class)
+ << FixItHint::CreateRemoval(StorageClassSpecLoc);
+
// C++ [class.friend]p6:
// No storage-class-specifier shall appear in the decl-specifier-seq
// of a friend declaration.
OpenPOWER on IntegriCloud