Author: rsmith Date: Mon May 14 13:15:04 2018 New Revision: 332286 URL: http://llvm.org/viewvc/llvm-project?rev=332286&view=rev Log: PR37450: Fix bug that disabled some type checks for variables with deduced types.
Also improve diagnostic for the case where a type is non-literal because it's a lambda. Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaType.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp cfe/trunk/test/SemaCXX/for-range-examples.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=332286&r1=332285&r2=332286&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon May 14 13:15:04 2018 @@ -2381,6 +2381,8 @@ def note_non_literal_user_provided_dtor "%0 is not literal because it has a user-provided destructor">; def note_non_literal_nontrivial_dtor : Note< "%0 is not literal because it has a non-trivial destructor">; +def note_non_literal_lambda : Note< + "lambda closure types are non-literal types before C++17">; def warn_private_extern : Warning< "use of __private_extern__ on a declaration may not produce external symbol " "private to the linkage unit and is deprecated">, InGroup<PrivateExtern>; Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=332286&r1=332285&r2=332286&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon May 14 13:15:04 2018 @@ -7293,8 +7293,7 @@ void Sema::CheckVariableDeclarationType( if (NewVD->isInvalidDecl()) return; - TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo(); - QualType T = TInfo->getType(); + QualType T = NewVD->getType(); // Defer checking an 'auto' type until its initializer is attached. if (T->isUndeducedType()) @@ -7438,10 +7437,18 @@ void Sema::CheckVariableDeclarationType( (T->isVariableArrayType() && NewVD->hasGlobalStorage())) { bool SizeIsNegative; llvm::APSInt Oversized; - TypeSourceInfo *FixedTInfo = - TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context, - SizeIsNegative, Oversized); - if (!FixedTInfo && T->isVariableArrayType()) { + TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo( + NewVD->getTypeSourceInfo(), Context, SizeIsNegative, Oversized); + QualType FixedT; + if (FixedTInfo && T == NewVD->getTypeSourceInfo()->getType()) + FixedT = FixedTInfo->getType(); + else if (FixedTInfo) { + // Type and type-as-written are canonically different. We need to fix up + // both types separately. + FixedT = TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, + Oversized); + } + if ((!FixedTInfo || FixedT.isNull()) && T->isVariableArrayType()) { const VariableArrayType *VAT = Context.getAsVariableArrayType(T); // FIXME: This won't give the correct result for // int a[10][n]; @@ -7470,7 +7477,7 @@ void Sema::CheckVariableDeclarationType( } Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); - NewVD->setType(FixedTInfo->getType()); + NewVD->setType(FixedT); NewVD->setTypeSourceInfo(FixedTInfo); } Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=332286&r1=332285&r2=332286&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Mon May 14 13:15:04 2018 @@ -7809,6 +7809,13 @@ bool Sema::RequireLiteralType(SourceLoca if (RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T)) return true; + // [expr.prim.lambda]p3: + // This class type is [not] a literal type. + if (RD->isLambda() && !getLangOpts().CPlusPlus17) { + Diag(RD->getLocation(), diag::note_non_literal_lambda); + return true; + } + // If the class has virtual base classes, then it's not an aggregate, and // cannot have any constexpr constructors or a trivial default constructor, // so is non-literal. This is better to diagnose than the resulting absence Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp?rev=332286&r1=332285&r2=332286&view=diff ============================================================================== --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp Mon May 14 13:15:04 2018 @@ -1,11 +1,19 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify +// RUN: %clang_cc1 -fsyntax-only -std=c++14 %s -verify +// RUN: %clang_cc1 -fsyntax-only -std=c++17 %s -verify void test_nonaggregate(int i) { auto lambda = [i]() -> void {}; // expected-note 2{{candidate constructor}} decltype(lambda) foo = { 1 }; // expected-error{{no matching constructor}} - static_assert(!__is_literal(decltype(lambda)), ""); + static_assert(__is_literal(decltype(lambda)) == (__cplusplus >= 201703L), ""); auto lambda2 = []{}; // expected-note 2{{candidate constructor}} decltype(lambda2) bar = {}; // expected-error{{no matching constructor}} - static_assert(!__is_literal(decltype(lambda2)), ""); + static_assert(__is_literal(decltype(lambda2)) == (__cplusplus >= 201703L), ""); } + +constexpr auto literal = []{}; +#if __cplusplus < 201703L +// expected-error@-2 {{constexpr variable cannot have non-literal type}} +// expected-note@-3 {{lambda closure types are non-literal types before C++17}} +#endif Modified: cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp?rev=332286&r1=332285&r2=332286&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp Mon May 14 13:15:04 2018 @@ -6,7 +6,7 @@ namespace test_lambda_is_literal { #ifdef CPP14_AND_EARLIER //expected-error@+4{{not a literal type}} -//expected-note@+2{{not an aggregate and has no constexpr constructors}} +//expected-note@+2{{lambda closure types are non-literal types before C++17}} #endif auto L = [] { }; constexpr int foo(decltype(L) l) { return 0; } Modified: cfe/trunk/test/SemaCXX/for-range-examples.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-examples.cpp?rev=332286&r1=332285&r2=332286&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/for-range-examples.cpp (original) +++ cfe/trunk/test/SemaCXX/for-range-examples.cpp Mon May 14 13:15:04 2018 @@ -221,11 +221,7 @@ namespace test7 { for (c alignas(8) : arr) { // expected-error {{requires type for loop variable}} static_assert(alignof(c) == 8, ""); // expected-warning {{extension}} } - // FIXME: The fix-it hint here is not sufficient to fix the error. - // We fail to diagnose that d is underaligned for its type, because - // we check the alignment attribute before we perform the auto - // deduction. - for (d alignas(1) : arr) {} // expected-error {{requires type for loop variable}} + for (d alignas(1) : arr) {} // expected-error {{requested alignment is less than minimum alignment of 8 for type 'int &'}} expected-error {{requires type for loop variable}} for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-error {{requires type for loop variable}} } } @@ -274,4 +270,4 @@ int foo(int b) { }(); return b; } -} \ No newline at end of file +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits