From: Haojian Wu Date: Fri, 27 Mar 2020 15:21:36 +0000 (+0100) Subject: [AST] Fix crashes on decltype(recovery-expr). X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6f428e09fbe8ce7e3510ae024031a5fc19653483;p=platform%2Fupstream%2Fllvm.git [AST] Fix crashes on decltype(recovery-expr). Summary: We mark these decls as invalid. Reviewers: sammccall Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D77037 --- diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h index 75c9aa16..0b24bae 100644 --- a/clang/include/clang/AST/DependenceFlags.h +++ b/clang/include/clang/AST/DependenceFlags.h @@ -50,14 +50,16 @@ struct TypeDependenceScope { /// Whether this type is a variably-modified type (C99 6.7.5). VariablyModified = 8, - // FIXME: add Error bit. + /// Whether this type references an error, e.g. decltype(err-expression) + /// yields an error type. + Error = 16, None = 0, - All = 15, + All = 31, DependentInstantiation = Dependent | Instantiation, - LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified) + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) }; }; using TypeDependence = TypeDependenceScope::TypeDependence; @@ -147,6 +149,7 @@ public: return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) | translate(V, Instantiation, TypeDependence::Instantiation) | translate(V, Dependent, TypeDependence::Dependent) | + translate(V, Error, TypeDependence::Error) | translate(V, VariablyModified, TypeDependence::VariablyModified); } diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 248fbcf..5d2c035 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2139,6 +2139,11 @@ public: return static_cast(TypeBits.Dependence); } + /// Whether this type is an error type. + bool containsErrors() const { + return getDependence() & TypeDependence::Error; + } + /// Whether this type is a dependent type, meaning that its definition /// somehow depends on a template parameter (C++ [temp.dep.type]). bool isDependentType() const { diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 761fad9..4389c87 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -3105,10 +3105,14 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { auto RunSignatureHelp = [&]() { ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); - assert(TypeRep && "invalid types should be handled before"); - QualType PreferredType = Actions.ProduceConstructorSignatureHelp( - getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), - DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); + QualType PreferredType; + // ActOnTypeName might adjust DeclaratorInfo and return a null type even + // the passing DeclaratorInfo is valid, e.g. running SignatureHelp on + // `new decltype(invalid) (^)`. + if (TypeRep) + PreferredType = Actions.ProduceConstructorSignatureHelp( + getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), + DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); CalledSignatureHelp = true; return PreferredType; }; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 55ce028..e128ebf 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1678,6 +1678,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { break; } + // FIXME: we want resulting declarations to be marked invalid, but claiming + // the type is invalid is too strong - e.g. it causes ActOnTypeName to return + // a null type. + if (Result->containsErrors()) + declarator.setInvalidType(); + if (S.getLangOpts().OpenCL && S.checkOpenCLDisabledTypeDeclSpec(DS, Result)) declarator.setInvalidType(true); diff --git a/clang/test/AST/ast-dump-expr-errors.cpp b/clang/test/AST/ast-dump-expr-errors.cpp index e623fad..9334b73 100644 --- a/clang/test/AST/ast-dump-expr-errors.cpp +++ b/clang/test/AST/ast-dump-expr-errors.cpp @@ -42,5 +42,9 @@ int d = static_cast(bar() + 1); // FIXME: store initializer even when 'auto' could not be deduced. // Expressions with errors currently do not keep initializers around. -// CHECK: `-VarDecl {{.*}} invalid e 'auto' +// CHECK: -VarDecl {{.*}} invalid e 'auto' auto e = bar(); + +// Error type should result in an invalid decl. +// CHECK: -VarDecl {{.*}} invalid f 'decltype((bar))' +decltype(bar()) f; diff --git a/clang/test/Sema/invalid-member.cpp b/clang/test/Sema/invalid-member.cpp index 5475157..5449799 100644 --- a/clang/test/Sema/invalid-member.cpp +++ b/clang/test/Sema/invalid-member.cpp @@ -1,7 +1,15 @@ -// RUN: %clang_cc1 -verify -fsyntax-only %s -void foo(); // expected-note {{requires 0 arguments}} +// RUN: %clang_cc1 -verify -fsyntax-only -fno-recovery-ast %s +// RUN: %clang_cc1 -verify -fsyntax-only -frecovery-ast %s + +void foo(); // expected-note 2{{requires 0 arguments}} class X { decltype(foo(42)) invalid; // expected-error {{no matching function}} }; // Should be able to evaluate sizeof without crashing. static_assert(sizeof(X) == 1, "No valid members"); + +class Y { + typeof(foo(42)) invalid; // expected-error {{no matching function}} +}; +// Should be able to evaluate sizeof without crashing. +static_assert(sizeof(Y) == 1, "No valid members"); diff --git a/clang/unittests/Sema/CodeCompleteTest.cpp b/clang/unittests/Sema/CodeCompleteTest.cpp index a9441a6..d8b303d 100644 --- a/clang/unittests/Sema/CodeCompleteTest.cpp +++ b/clang/unittests/Sema/CodeCompleteTest.cpp @@ -486,7 +486,10 @@ TEST(PreferredTypeTest, NoCrashOnInvalidTypes) { StringRef Code = R"cpp( auto x = decltype(&1)(^); auto y = new decltype(&1)(^); + // GNU decimal type extension is not supported in clang. + auto z = new _Decimal128(^); )cpp"; EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE")); } + } // namespace