diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-09-04 19:54:14 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-09-04 19:54:14 +0000 |
commit | 58c743370994da37df3c6ebba76a8277af8483e0 (patch) | |
tree | 00d4ed51761297f5bc38225ba635184165444a41 /clang/lib/Sema | |
parent | e9c4e84f8ea7a8245b1cbb44e158cf0b8d29eb28 (diff) | |
download | bcm5719-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.cpp | 36 |
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. |