From: Richard Smith Date: Tue, 7 May 2019 07:36:07 +0000 (+0000) Subject: Improve function / variable disambiguation. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=983fd48a00d938a22152c9434376786544d2dce5;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@360117 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 21a656319c..f5c404f7e6 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/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/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 46366ff43c..de9391cddd 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/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/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index 4f3e2faa8e..8c09947ad7 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/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/test/CodeGen/builtins-ppc-altivec.c b/test/CodeGen/builtins-ppc-altivec.c index 13562354f4..e7ba7167cf 100644 --- a/test/CodeGen/builtins-ppc-altivec.c +++ b/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> {{.*}}, // 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/test/Parser/cxx-ambig-decl-expr.cpp b/test/Parser/cxx-ambig-decl-expr.cpp index 7bf08b02c4..6507eafb74 100644 --- a/test/Parser/cxx-ambig-decl-expr.cpp +++ b/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'}}