diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-07 07:36:07 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-07 07:36:07 +0000 |
commit | b30657938ce943a786de8b7dbb829c11003b74f5 (patch) | |
tree | d67c79e492b5f676b1b5df38a3f27055e5f4a3ad | |
parent | c094912ae53546b100b1c3ddc262345a235cea55 (diff) | |
download | bcm5719-llvm-b30657938ce943a786de8b7dbb829c11003b74f5.tar.gz bcm5719-llvm-b30657938ce943a786de8b7dbb829c11003b74f5.zip |
Improve function / variable disambiguation.
Keep looking for decl-specifiers after an unknown identifier. Don't
issue diagnostics about an error type specifier conflicting with later
type specifiers.
llvm-svn: 360117
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 22 | ||||
-rw-r--r-- | clang/test/CodeGen/builtins-ppc-altivec.c | 9 | ||||
-rw-r--r-- | clang/test/Parser/cxx-ambig-decl-expr.cpp | 2 |
5 files changed, 46 insertions, 33 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 21a656319c0..f5c404f7e62 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2743,7 +2743,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // TODO: Could inject an invalid typedef decl in an enclosing scope to // avoid rippling error messages on subsequent uses of the same type, // could be useful if #include was forgotten. - return false; + return true; } /// Determine the declaration specifier context from the declarator diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 46366ff43cf..de9391cddd7 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1884,31 +1884,31 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration, // decl-specifier-seq '{' is not a parameter in C++11. TPResult TPR = isCXXDeclarationSpecifier(TPResult::False, InvalidAsDeclaration); + // A declaration-specifier (not followed by '(' or '{') means this can't be + // an expression, but it could still be a template argument. + if (TPR != TPResult::Ambiguous && + !(VersusTemplateArgument && TPR == TPResult::True)) + return TPR; - if (VersusTemplateArgument && TPR == TPResult::True) { - // Consume the decl-specifier-seq. We have to look past it, since a - // type-id might appear here in a template argument. - bool SeenType = false; - do { - SeenType |= isCXXDeclarationSpecifierAType(); - if (TryConsumeDeclarationSpecifier() == TPResult::Error) - return TPResult::Error; - - // If we see a parameter name, this can't be a template argument. - if (SeenType && Tok.is(tok::identifier)) - return TPResult::True; - - TPR = isCXXDeclarationSpecifier(TPResult::False, - InvalidAsDeclaration); - if (TPR == TPResult::Error) - return TPR; - } while (TPR != TPResult::False); - } else if (TPR == TPResult::Ambiguous) { - // Disambiguate what follows the decl-specifier. + bool SeenType = false; + do { + SeenType |= isCXXDeclarationSpecifierAType(); if (TryConsumeDeclarationSpecifier() == TPResult::Error) return TPResult::Error; - } else - return TPR; + + // If we see a parameter name, this can't be a template argument. + if (SeenType && Tok.is(tok::identifier)) + return TPResult::True; + + TPR = isCXXDeclarationSpecifier(TPResult::False, + InvalidAsDeclaration); + if (TPR == TPResult::Error) + return TPR; + + // Two declaration-specifiers means this can't be an expression. + if (TPR == TPResult::True && !VersusTemplateArgument) + return TPR; + } while (TPR != TPResult::False); // declarator // abstract-declarator[opt] diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 4f3e2faa8e0..8c09947ad7b 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -706,6 +706,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, const PrintingPolicy &Policy) { assert(isTypeRep(T) && "T does not store a type"); assert(Rep && "no type provided!"); + if (TypeSpecType == TST_error) + return false; if (TypeSpecType != TST_unspecified) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); DiagID = diag::err_invalid_decl_spec_combination; @@ -726,6 +728,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, const PrintingPolicy &Policy) { assert(isExprRep(T) && "T does not store an expr"); assert(Rep && "no expression provided!"); + if (TypeSpecType == TST_error) + return false; if (TypeSpecType != TST_unspecified) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); DiagID = diag::err_invalid_decl_spec_combination; @@ -756,6 +760,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, assert(isDeclRep(T) && "T does not store a decl"); // Unlike the other cases, we don't assert that we actually get a decl. + if (TypeSpecType == TST_error) + return false; if (TypeSpecType != TST_unspecified) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); DiagID = diag::err_invalid_decl_spec_combination; @@ -775,6 +781,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, const PrintingPolicy &Policy) { assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) && "rep required for these type-spec kinds!"); + if (TypeSpecType == TST_error) + return false; if (TypeSpecType != TST_unspecified) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); DiagID = diag::err_invalid_decl_spec_combination; @@ -807,6 +815,8 @@ bool DeclSpec::SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec, bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { + if (TypeSpecType == TST_error) + return false; if (TypeSpecType != TST_unspecified) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); DiagID = diag::err_invalid_vector_decl_spec_combination; @@ -820,7 +830,8 @@ bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { - + if (TypeSpecType == TST_error) + return false; if (TypeSpecType != TST_unspecified) { PrevSpec = DeclSpec::getSpecifierName((TST)TypeSpecType, Policy); DiagID = diag::err_invalid_decl_spec_combination; @@ -836,6 +847,8 @@ bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc, bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { + if (TypeSpecType == TST_error) + return false; if (!TypeAltiVecVector || TypeAltiVecPixel || (TypeSpecType != TST_unspecified)) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); @@ -851,6 +864,8 @@ bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, bool DeclSpec::SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { + if (TypeSpecType == TST_error) + return false; if (!TypeAltiVecVector || TypeAltiVecBool || (TypeSpecType != TST_unspecified)) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); @@ -1033,7 +1048,10 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { // Before possibly changing their values, save specs as written. SaveWrittenBuiltinSpecs(); - // Check the type specifier components first. + // Check the type specifier components first. No checking for an invalid + // type. + if (TypeSpecType == TST_error) + return; // If decltype(auto) is used, no other type specifiers are permitted. if (TypeSpecType == TST_decltype_auto && diff --git a/clang/test/CodeGen/builtins-ppc-altivec.c b/clang/test/CodeGen/builtins-ppc-altivec.c index 13562354f4e..e7ba7167cf9 100644 --- a/clang/test/CodeGen/builtins-ppc-altivec.c +++ b/clang/test/CodeGen/builtins-ppc-altivec.c @@ -37,6 +37,7 @@ vector unsigned int res_vui; vector float res_vf; // CHECK-NOALTIVEC: error: unknown type name 'vector' +// CHECK-NOALTIVEC-NOT: '(error)' signed char param_sc; unsigned char param_uc; @@ -86,8 +87,6 @@ void test1() { // CHECK-LE: and <4 x i32> {{.*}}, <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647> // CHECK-LE: bitcast <4 x i32> %{{.*}} to <4 x float> // CHECK-LE: store <4 x float> %{{.*}}, <4 x float>* @vf -// CHECK-NOALTIVEC: error: use of undeclared identifier 'vf' -// CHECK-NOALTIVEC: vf = vec_abs(vf) vsc = vec_nabs(vsc); // CHECK: sub <16 x i8> zeroinitializer @@ -110,20 +109,14 @@ void test1() { res_vi = vec_neg(vi); // CHECK: sub <4 x i32> zeroinitializer, {{%[0-9]+}} // CHECK-LE: sub <4 x i32> zeroinitializer, {{%[0-9]+}} -// CHECK-NOALTIVEC: error: use of undeclared identifier 'vi' -// CHECK-NOALTIVEC: vi = vec_neg(vi); res_vs = vec_neg(vs); // CHECK: sub <8 x i16> zeroinitializer, {{%[0-9]+}} // CHECK-LE: sub <8 x i16> zeroinitializer, {{%[0-9]+}} -// CHECK-NOALTIVEC: error: use of undeclared identifier 'vs' -// CHECK-NOALTIVEC: res_vs = vec_neg(vs); res_vsc = vec_neg(vsc); // CHECK: sub <16 x i8> zeroinitializer, {{%[0-9]+}} // CHECK-LE: sub <16 x i8> zeroinitializer, {{%[0-9]+}} -// CHECK-NOALTIVEC: error: use of undeclared identifier 'vsc' -// CHECK-NOALTIVEC: res_vsc = vec_neg(vsc); /* vec_abs */ diff --git a/clang/test/Parser/cxx-ambig-decl-expr.cpp b/clang/test/Parser/cxx-ambig-decl-expr.cpp index 7bf08b02c4f..6507eafb74c 100644 --- a/clang/test/Parser/cxx-ambig-decl-expr.cpp +++ b/clang/test/Parser/cxx-ambig-decl-expr.cpp @@ -15,3 +15,5 @@ void f() { auto (*p)() -> int(nullptr); auto (*q)() -> int(*)(unknown); // expected-error {{unknown type name 'unknown'}} auto (*r)() -> int(*)(unknown + 1); // expected-error {{undeclared identifier 'unknown'}} + +int f(unknown const x); // expected-error {{unknown type name 'unknown'}} |