r372058 - Push lambda scope earlier when transforming lambda expression
Author: comex Date: Mon Sep 16 18:43:33 2019 New Revision: 372058 URL: http://llvm.org/viewvc/llvm-project?rev=372058&view=rev Log: Push lambda scope earlier when transforming lambda expression Differential Revision: https://reviews.llvm.org/D66067 Modified: cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=372058&r1=372057&r2=372058&view=diff == --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Sep 16 18:43:33 2019 @@ -11325,10 +11325,14 @@ TreeTransform::TransformLambdaE } } + LambdaScopeInfo *LSI = getSema().PushLambdaScope(); + Sema::FunctionScopeRAII FuncScopeCleanup(getSema()); + // Transform the template parameters, and add them to the current // instantiation scope. The null case is handled correctly. auto TPL = getDerived().TransformTemplateParameterList( E->getTemplateParameterList()); + LSI->GLTemplateParameterList = TPL; // Transform the type of the original lambda's call operator. // The transformation MUST be done in the CurrentInstantiationScope since @@ -11355,10 +11359,6 @@ TreeTransform::TransformLambdaE NewCallOpType); } - LambdaScopeInfo *LSI = getSema().PushLambdaScope(); - Sema::FunctionScopeRAII FuncScopeCleanup(getSema()); - LSI->GLTemplateParameterList = TPL; - // Create the local class that will describe the lambda. CXXRecordDecl *OldClass = E->getLambdaClass(); CXXRecordDecl *Class Modified: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp?rev=372058&r1=372057&r2=372058&view=diff == --- cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp (original) +++ cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp Mon Sep 16 18:43:33 2019 @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s // expected-no-diagnostics // Test default template arguments for function templates. @@ -114,3 +115,17 @@ namespace rdar34167492 { S _a{}; }; } + +#if __cplusplus >= 201402L +namespace lambda { + // Verify that a default argument in a lambda can refer to the type of a + // previous `auto` argument without crashing. + template + void bar() { +(void) [](auto c, int x = sizeof(decltype(c))) {}; + } + void foo() { +bar(); + } +} // namespace lambda +#endif ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r372361 - [Consumed] Treat by-value class arguments as consuming by default, like rvalue refs.
Author: comex Date: Thu Sep 19 16:00:31 2019 New Revision: 372361 URL: http://llvm.org/viewvc/llvm-project?rev=372361&view=rev Log: [Consumed] Treat by-value class arguments as consuming by default, like rvalue refs. Differential Revision: https://reviews.llvm.org/D67743 Modified: cfe/trunk/lib/Analysis/Consumed.cpp cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp Modified: cfe/trunk/lib/Analysis/Consumed.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/Consumed.cpp?rev=372361&r1=372360&r2=372361&view=diff == --- cfe/trunk/lib/Analysis/Consumed.cpp (original) +++ cfe/trunk/lib/Analysis/Consumed.cpp Thu Sep 19 16:00:31 2019 @@ -644,10 +644,10 @@ bool ConsumedStmtVisitor::handleCall(con continue; // Adjust state on the caller side. -if (isRValueRef(ParamType)) - setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed); -else if (ReturnTypestateAttr *RT = Param->getAttr()) +if (ReturnTypestateAttr *RT = Param->getAttr()) setStateForVarOrTmp(StateMap, PInfo, mapReturnTypestateAttrState(RT)); +else if (isRValueRef(ParamType) || isConsumableType(ParamType)) + setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed); else if (isPointerOrRef(ParamType) && (!ParamType->getPointeeType().isConstQualified() || isSetOnReadPtrType(ParamType))) Modified: cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp?rev=372361&r1=372360&r2=372361&view=diff == --- cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp Thu Sep 19 16:00:31 2019 @@ -53,12 +53,18 @@ class CONSUMABLE(unconsumed) DestructorT public: DestructorTester(); DestructorTester(int); + DestructorTester(nullptr_t) RETURN_TYPESTATE(unconsumed); + DestructorTester(DestructorTester &&); void operator*() CALLABLE_WHEN("unconsumed"); ~DestructorTester() CALLABLE_WHEN("consumed"); + }; +void dtByVal(DestructorTester); +void dtByValMarkUnconsumed(DestructorTester RETURN_TYPESTATE(unconsumed)); + void baf0(const ConsumableClass var); void baf1(const ConsumableClass &var); void baf2(const ConsumableClass *var); @@ -120,6 +126,19 @@ void testDestruction() { expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}} } +void testDestructionByVal() { + { +// both the var and the temporary are consumed: +DestructorTester D0(nullptr); +dtByVal((DestructorTester &&)D0); + } + { +// the var is consumed but the temporary isn't: +DestructorTester D1(nullptr); +dtByValMarkUnconsumed((DestructorTester &&)D1); // expected-warning {{invalid invocation of method '~DestructorTester' on a temporary object while it is in the 'unconsumed' state}} + } +} + void testTempValue() { *ConsumableClass(); // expected-warning {{invalid invocation of method 'operator*' on a temporary object while it is in the 'consumed' state}} } @@ -413,10 +432,15 @@ void testParamReturnTypestateCallee(bool Param.consume(); } +void testRvalueRefParamReturnTypestateCallee(ConsumableClass &&Param RETURN_TYPESTATE(unconsumed)) { + Param.unconsume(); +} + void testParamReturnTypestateCaller() { ConsumableClass var; testParamReturnTypestateCallee(true, var); + testRvalueRefParamReturnTypestateCallee((ConsumableClass &&)var); *var; } @@ -480,6 +504,9 @@ void testCallingConventions() { baf2(&var); *var; + + baf3(var); + *var; baf4(var); *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r373034 - [Consumed][NFC] Refactor handleCall to take function argument list.
Author: comex Date: Thu Sep 26 16:47:18 2019 New Revision: 373034 URL: http://llvm.org/viewvc/llvm-project?rev=373034&view=rev Log: [Consumed][NFC] Refactor handleCall to take function argument list. Differential Revision: https://reviews.llvm.org/D67569 Modified: cfe/trunk/include/clang/AST/Stmt.h cfe/trunk/lib/Analysis/Consumed.cpp Modified: cfe/trunk/include/clang/AST/Stmt.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=373034&r1=373033&r2=373034&view=diff == --- cfe/trunk/include/clang/AST/Stmt.h (original) +++ cfe/trunk/include/clang/AST/Stmt.h Thu Sep 26 16:47:18 2019 @@ -1041,7 +1041,8 @@ protected: template struct CastIterator : llvm::iterator_adaptor_base, StmtPtr *, -std::random_access_iterator_tag, TPtr> { +std::random_access_iterator_tag, TPtr, +int, void, TPtr> { using Base = typename CastIterator::iterator_adaptor_base; CastIterator() : Base(nullptr) {} Modified: cfe/trunk/lib/Analysis/Consumed.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/Consumed.cpp?rev=373034&r1=373033&r2=373034&view=diff == --- cfe/trunk/lib/Analysis/Consumed.cpp (original) +++ cfe/trunk/lib/Analysis/Consumed.cpp Thu Sep 26 16:47:18 2019 @@ -494,8 +494,10 @@ public: void checkCallability(const PropagationInfo &PInfo, const FunctionDecl *FunDecl, SourceLocation BlameLoc); - bool handleCall(const CallExpr *Call, const Expr *ObjArg, - const FunctionDecl *FunD); + + using ArgRange = llvm::iterator_range; + bool handleCall(const Expr *Call, const Expr *ObjArg, + ArgRange args, const FunctionDecl *FunD); void VisitBinaryOperator(const BinaryOperator *BinOp); void VisitCallExpr(const CallExpr *Call); @@ -608,22 +610,21 @@ void ConsumedStmtVisitor::checkCallabili // Factors out common behavior for function, method, and operator calls. // Check parameters and set parameter state if necessary. // Returns true if the state of ObjArg is set, or false otherwise. -bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg, +bool ConsumedStmtVisitor::handleCall(const Expr *Call, + const Expr *ObjArg, + ArgRange Args, const FunctionDecl *FunD) { - unsigned Offset = 0; - if (isa(Call) && isa(FunD)) -Offset = 1; // first argument is 'this' - // check explicit parameters - for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) { + unsigned Index = 0; + for (const Expr *Arg : Args) { // Skip variable argument lists. -if (Index - Offset >= FunD->getNumParams()) +if (Index >= FunD->getNumParams()) break; -const ParmVarDecl *Param = FunD->getParamDecl(Index - Offset); +const ParmVarDecl *Param = FunD->getParamDecl(Index++); QualType ParamType = Param->getType(); -InfoEntry Entry = findInfo(Call->getArg(Index)); +InfoEntry Entry = findInfo(Arg); if (Entry == PropagationMap.end() || Entry->second.isTest()) continue; @@ -636,7 +637,7 @@ bool ConsumedStmtVisitor::handleCall(con if (ParamState != ExpectedState) Analyzer.WarningsHandler.warnParamTypestateMismatch( - Call->getArg(Index)->getExprLoc(), + Arg->getExprLoc(), stateToString(ExpectedState), stateToString(ParamState)); } @@ -749,7 +750,7 @@ void ConsumedStmtVisitor::VisitCallExpr( return; } - handleCall(Call, nullptr, FunDecl); + handleCall(Call, nullptr, Call->arguments(), FunDecl); propagateReturnType(Call, FunDecl); } @@ -805,7 +806,7 @@ void ConsumedStmtVisitor::VisitCXXMember if (!MD) return; - handleCall(Call, Call->getImplicitObjectArgument(), MD); + handleCall(Call, Call->getImplicitObjectArgument(), Call->arguments(), MD); propagateReturnType(Call, MD); } @@ -813,18 +814,20 @@ void ConsumedStmtVisitor::VisitCXXOperat const CXXOperatorCallExpr *Call) { const auto *FunDecl = dyn_cast_or_null(Call->getDirectCallee()); if (!FunDecl) return; + ArgRange Args = Call->arguments(); if (Call->getOperator() == OO_Equal) { -ConsumedState CS = getInfo(Call->getArg(1)); -if (!handleCall(Call, Call->getArg(0), FunDecl)) - setInfo(Call->getArg(0), CS); +ConsumedState CS = getInfo(llvm::index(Args, 1)); +if (!handleCall(Call, llvm::index(Args, 0), llvm::drop_begin(Args, 1), +FunDecl)) + setInfo(llvm::index(Args, 0), CS); return; } - if (const auto *MCall = dyn_cast(Call)) -handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl); + if (isa(FunDecl)) +handleCall(Ca
r373039 - Revert r373034
Author: comex Date: Thu Sep 26 18:58:31 2019 New Revision: 373039 URL: http://llvm.org/viewvc/llvm-project?rev=373039&view=rev Log: Revert r373034 It breaks the build on MSVC. Modified: cfe/trunk/include/clang/AST/Stmt.h cfe/trunk/lib/Analysis/Consumed.cpp Modified: cfe/trunk/include/clang/AST/Stmt.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=373039&r1=373038&r2=373039&view=diff == --- cfe/trunk/include/clang/AST/Stmt.h (original) +++ cfe/trunk/include/clang/AST/Stmt.h Thu Sep 26 18:58:31 2019 @@ -1041,8 +1041,7 @@ protected: template struct CastIterator : llvm::iterator_adaptor_base, StmtPtr *, -std::random_access_iterator_tag, TPtr, -int, void, TPtr> { +std::random_access_iterator_tag, TPtr> { using Base = typename CastIterator::iterator_adaptor_base; CastIterator() : Base(nullptr) {} Modified: cfe/trunk/lib/Analysis/Consumed.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/Consumed.cpp?rev=373039&r1=373038&r2=373039&view=diff == --- cfe/trunk/lib/Analysis/Consumed.cpp (original) +++ cfe/trunk/lib/Analysis/Consumed.cpp Thu Sep 26 18:58:31 2019 @@ -494,10 +494,8 @@ public: void checkCallability(const PropagationInfo &PInfo, const FunctionDecl *FunDecl, SourceLocation BlameLoc); - - using ArgRange = llvm::iterator_range; - bool handleCall(const Expr *Call, const Expr *ObjArg, - ArgRange args, const FunctionDecl *FunD); + bool handleCall(const CallExpr *Call, const Expr *ObjArg, + const FunctionDecl *FunD); void VisitBinaryOperator(const BinaryOperator *BinOp); void VisitCallExpr(const CallExpr *Call); @@ -610,21 +608,22 @@ void ConsumedStmtVisitor::checkCallabili // Factors out common behavior for function, method, and operator calls. // Check parameters and set parameter state if necessary. // Returns true if the state of ObjArg is set, or false otherwise. -bool ConsumedStmtVisitor::handleCall(const Expr *Call, - const Expr *ObjArg, - ArgRange Args, +bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg, const FunctionDecl *FunD) { + unsigned Offset = 0; + if (isa(Call) && isa(FunD)) +Offset = 1; // first argument is 'this' + // check explicit parameters - unsigned Index = 0; - for (const Expr *Arg : Args) { + for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) { // Skip variable argument lists. -if (Index >= FunD->getNumParams()) +if (Index - Offset >= FunD->getNumParams()) break; -const ParmVarDecl *Param = FunD->getParamDecl(Index++); +const ParmVarDecl *Param = FunD->getParamDecl(Index - Offset); QualType ParamType = Param->getType(); -InfoEntry Entry = findInfo(Arg); +InfoEntry Entry = findInfo(Call->getArg(Index)); if (Entry == PropagationMap.end() || Entry->second.isTest()) continue; @@ -637,7 +636,7 @@ bool ConsumedStmtVisitor::handleCall(con if (ParamState != ExpectedState) Analyzer.WarningsHandler.warnParamTypestateMismatch( - Arg->getExprLoc(), + Call->getArg(Index)->getExprLoc(), stateToString(ExpectedState), stateToString(ParamState)); } @@ -750,7 +749,7 @@ void ConsumedStmtVisitor::VisitCallExpr( return; } - handleCall(Call, nullptr, Call->arguments(), FunDecl); + handleCall(Call, nullptr, FunDecl); propagateReturnType(Call, FunDecl); } @@ -806,7 +805,7 @@ void ConsumedStmtVisitor::VisitCXXMember if (!MD) return; - handleCall(Call, Call->getImplicitObjectArgument(), Call->arguments(), MD); + handleCall(Call, Call->getImplicitObjectArgument(), MD); propagateReturnType(Call, MD); } @@ -814,20 +813,18 @@ void ConsumedStmtVisitor::VisitCXXOperat const CXXOperatorCallExpr *Call) { const auto *FunDecl = dyn_cast_or_null(Call->getDirectCallee()); if (!FunDecl) return; - ArgRange Args = Call->arguments(); if (Call->getOperator() == OO_Equal) { -ConsumedState CS = getInfo(llvm::index(Args, 1)); -if (!handleCall(Call, llvm::index(Args, 0), llvm::drop_begin(Args, 1), -FunDecl)) - setInfo(llvm::index(Args, 0), CS); +ConsumedState CS = getInfo(Call->getArg(1)); +if (!handleCall(Call, Call->getArg(0), FunDecl)) + setInfo(Call->getArg(0), CS); return; } - if (isa(FunDecl)) -handleCall(Call, llvm::index(Args, 0), llvm::drop_begin(Args, 1), FunDecl); + if (const auto *MCall = dyn_cast(Call)) +handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl); else -han
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex updated the summary for this revision. comex updated this revision to Diff 34787. comex added a comment. Per vsk: - Changed to an explicit switch, and changed ContainsPlaceholderType logic. Note: Currently, GetDeclSpecTypeForDeclarator determines ContainsPlaceholderType at two different levels depending on the context: usually it calls containsPlaceholderType on the DeclSpec, but for conversion methods it searches the Type itself using getContainedAutoType. This confused me, because I can't come up with any conversion method declaration that would actually yield different answers for those predicates, given the definition of getContainedAutoType - at least that wouldn't generate an error elsewhere. (They're different in the case of an auto lambda parameter, in which case the AutoType has already been converted to a dependent template type, but that's not a conversion.) The old patch implicitly assumed containsPlaceholderType was true when it checked getTypeSpecType; I could avoid this by determining which auto keyword is being used a different way in the conversion case, but since that would be really ugly, I went ahead and removed ContainsPlaceholderType in favor of always calling containsPlaceholderType, effectively partially reverting SVN revision 181108. This might be wrong. For example, these all still properly fail with this patch: template struct F {}; struct A { operator auto() {} operator auto*() {} operator auto*() {} operator F() {} operator auto() -> auto {} operator __typeof__(auto(*)())() {} operator __typeof__([](auto){})() {} // bad error though (unaffected by patch) }; I did come up with this snippet which trips an assertion in stock Clang (also unaffected by this patch): typedef __typeof__(auto()) *T; T lol = (T) 2; ...and here's another one: typedef &decltype(auto)::x T; I guess I should report these separately. - Added error for using `__auto_type` with a bitfield in C; since it was easy, I also added the same for typeof, despite it not being strictly related. Per rsmith: - Changed enum struct to enum class, and AutoTypeExt to GNUAutoType. - As far as I understand, having distinguishable values profile the same would break uniquing - in this case, that done in getAutoType(). In theory, mangling shouldn't be a problem because the cases where 'auto' ends up being mangled shouldn't be allowed with `__auto_type`: AFAICT only C++14 (template) functions with deduced return types. But it turns out I wasn't properly banning those, which I fixed. I also added an assertion to the two manglers that `__auto_type` isn't encountered. - Fixed whitespace and removed getTypePtr(). Also: - Improved error message with code like `__auto_type x = {2, 3};` in C (previously it referred to std::initializer_list) http://reviews.llvm.org/D12686 Files: include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/Specifiers.h include/clang/Basic/TokenKinds.def include/clang/Sema/DeclSpec.h lib/AST/ASTContext.cpp lib/AST/ASTImporter.cpp lib/AST/ItaniumMangle.cpp lib/AST/MicrosoftMangle.cpp lib/AST/Type.cpp lib/AST/TypePrinter.cpp lib/Format/TokenAnnotator.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseTentative.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp test/Sema/auto-type.c test/Sema/bitfield.c test/Sema/exprs.c test/SemaCXX/auto-type-from-cxx.cpp Index: test/SemaCXX/auto-type-from-cxx.cpp === --- /dev/null +++ test/SemaCXX/auto-type-from-cxx.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s + +__auto_type a() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not '__auto_type'}} +template +__auto_type b() { return T::x; } // expected-error {{'__auto_type' not allowed in function return type}} +auto c() -> __auto_type { __builtin_unreachable(); } // expected-error {{'__auto_type' not allowed in function return type}} +int d() { + decltype(__auto_type) e = 1; // expected-error {{expected expression}} + auto _ = [](__auto_type f) {}; // expected-error {{'__auto_type' not allowed in lambda parameter}} + __auto_type g = 2; + struct BitField { int field:2; }; + __auto_type h = BitField{1}.field; // (should work from C++) +} + Index: test/Sema/exprs.c === --- test/Sema/exprs.c +++ test/Sema/exprs.c @@ -97,6 +97,
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex added a comment. Ping? http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex created this revision. comex added a subscriber: cfe-commits. Herald added subscribers: aemerson, klimek. Add support for GCC's '__auto_type' extension. As per the GCC manual: https://gcc.gnu.org/onlinedocs/gcc/Typeof.html Implemented in GCC 4.9, __auto_type is similar to C++11 auto but works in C. The most compelling use case is for macros; the above manual page explains the need pretty well, so I won't repeat it here. This implementation differs from GCC's in also supporting __auto_type in C++, treating it the same as auto. I don't see any good reason not to, because otherwise headers intended to be used from both languages can't use it (you could use a define that expands to '__auto_type' or 'auto' depending on the language, but then C++ pre-11 is broken). However, for sanity's sake, it prevents using __auto_type instead of auto with C++11+-specific functionality such as 'decltype(auto)', auto arguments to lambdas, and auto before a trailing return type. **It also differs by allowing all of the following (by default, due to reusing the C++ auto behavior) which GCC rejects: initializing with the value of a bit field, using '__auto_type *', and declaring multiple variables in one statement. (The first of those extends a preexisting difference: GCC does not allow typeof on a bit field, while Clang currently does. Arguably a bug, as the C standard prohibits using sizeof on them.) Maybe this should be tightened for the sake of compatibility, although it doesn't otherwise seem harmful to allow them (the latter two, anyway). Opinions desired. Making this work in clang is pretty straightforward: most of the patch is only needed to fix up diagnostics. (This is my first patch submission, so please let me know if I've done things wrong.) http://reviews.llvm.org/D12686 Files: include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/Specifiers.h include/clang/Basic/TokenKinds.def include/clang/Sema/DeclSpec.h lib/AST/ASTContext.cpp lib/AST/ASTImporter.cpp lib/AST/Type.cpp lib/AST/TypePrinter.cpp lib/Format/TokenAnnotator.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseTentative.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp test/Sema/auto-type.c test/SemaCXX/auto-type-from-cxx.cpp Index: test/SemaCXX/auto-type-from-cxx.cpp === --- /dev/null +++ test/SemaCXX/auto-type-from-cxx.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s + +__auto_type a() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not '__auto_type'}} +int b() { + decltype(__auto_type) c = 1; // expected-error {{expected expression}} + auto _ = [](__auto_type d) {}; // expected-error {{'__auto_type' not allowed in lambda parameter}} + __auto_type e = 2; +} + Index: test/Sema/auto-type.c === --- /dev/null +++ test/Sema/auto-type.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic -std=c11 + +__auto_type a = 5; // expected-warning {{'__auto_type' is a GNU extension}} +__extension__ __auto_type a1 = 5; +#pragma clang diagnostic ignored "-Wgnu-auto-type" +__auto_type b = 5.0; +__auto_type c = &b; +__auto_type d = (struct {int a;}) {5}; +_Static_assert(__builtin_types_compatible_p(__typeof(a), int), ""); +__auto_type e = e; // expected-error {{variable 'e' declared with '__auto_type' type cannot appear in its own initializer}} + +struct s { __auto_type a; }; // expected-error {{'__auto_type' not allowed in struct member}} + +__auto_type f = 1, g = 1.0; // expected-error {{'__auto_type' deduced as 'int' in declaration of 'f' and deduced as 'double' in declaration of 'g'}} + +__auto_type a() {} // expected-error {{'__auto_type' not allowed in function return type}} Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp === --- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp +++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp @@ -3,9 +3,9 @@ // FIXME: This is in p11 (?) in C++1y. void f() { - decltype(auto) a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}} - if (decltype(auto) b = b) {} // expected-error {{variable 'b' declared with 'auto' type cannot appear in its own initializer}} - decltype(auto) c = ({ decltype(auto) d = c; 0; }); // expected-error {{variable
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex added a comment. Ping again. http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex marked 5 inline comments as done. Comment at: include/clang/Basic/DiagnosticSemaKinds.td:1726 @@ -1720,1 +1725,3 @@ +def err_auto_bitfield : Error< + "cannot pass bit-field as __auto_type initializer in C">; rsmith wrote: > pass -> use > > Also, why not? Just because GCC messes this up, doesn't mean we have to. By analogy with the standards-defined inability to use sizeof on bit fields, it made sense to me to do what GCC does and forbid getting their type in other ways. Though I suppose the restriction is somewhat questionable in the first place. Comment at: lib/AST/ItaniumMangle.cpp:2557-2558 @@ -2557,1 +2556,4 @@ + if (D.isNull()) { +assert(T->getKeyword() != AutoTypeKeyword::GNUAutoType && + "shouldn't need to mangle __auto_type!"); Out << (T->isDecltypeAuto() ? "Dc" : "Da"); rsmith wrote: > Why not? > > template void f(decltype(new __auto_type(T(; > > ... would need a mangling, right? (Or do you prohibit `__auto_type` there?) Since my goal is to only allow `__auto_type` in C-compatible contexts, this should be prohibited, but wasn't. Fixed. (Any other cases I haven't thought of?) Comment at: lib/Parse/ParseDeclCXX.cpp:1119 @@ -1118,2 +1118,3 @@ case tok::kw_auto:// struct foo {...} auto x; + case tok::kw___auto_type: // struct foo {...} __auto_type x; case tok::kw_mutable: // struct foo {...} mutable x; rsmith wrote: > That would be ill-formed; revert this change. Fixed. Durr. Comment at: lib/Sema/SemaType.cpp:1457 @@ -1455,3 +1456,3 @@ // being analyzed (which tracks the invented type template parameter). if (declarator.getContext() == Declarator::LambdaExprParameterContext) { sema::LambdaScopeInfo *LSI = S.getCurLambda(); rsmith wrote: > Should we really allow using `__auto_type` to introduce a generic lambda? It > seems like there's a major open design question here: either we should allow > `__auto_type` only in GCC-compatible contexts (that is, as a decl-specifier > that's not a function return type), or we should allow it everywhere we allow > `auto` and make it a synonym for `auto` in C++ (in which case it needs to be > mangled, and the distinction between `auto` and `__auto_type` should probably > not affect the canonical type). My goal was to do the former; if you'd prefer to just make it a synonym. In this case, the patch prevents `__auto_type` from being used in lambda parameters elsewhere. http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex updated the summary for this revision. comex updated this revision to Diff 37202. comex marked 3 inline comments as done. comex added a comment. Fixed raised issues. (I don't have commit rights.) http://reviews.llvm.org/D12686 Files: include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/Specifiers.h include/clang/Basic/TokenKinds.def include/clang/Sema/DeclSpec.h lib/AST/ASTContext.cpp lib/AST/ASTImporter.cpp lib/AST/ItaniumMangle.cpp lib/AST/MicrosoftMangle.cpp lib/AST/Type.cpp lib/AST/TypePrinter.cpp lib/Format/TokenAnnotator.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseTentative.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp test/Sema/auto-type.c test/Sema/bitfield.c test/Sema/exprs.c test/SemaCXX/auto-type-from-cxx.cpp Index: test/SemaCXX/auto-type-from-cxx.cpp === --- /dev/null +++ test/SemaCXX/auto-type-from-cxx.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s + +struct A { +operator __auto_type() {} // expected-error {{'__auto_type' not allowed in conversion function type}} +}; + +__auto_type a() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not '__auto_type'}} +template +__auto_type b() { return T::x; } // expected-error {{'__auto_type' not allowed in function return type}} +auto c() -> __auto_type { __builtin_unreachable(); } // expected-error {{'__auto_type' not allowed in function return type}} +int d() { + decltype(__auto_type) e = 1; // expected-error {{expected expression}} + auto _ = [](__auto_type f) {}; // expected-error {{'__auto_type' not allowed in lambda parameter}} + __auto_type g = 2; + struct BitField { int field:2; }; + __auto_type h = BitField{1}.field; // (should work from C++) + new __auto_type; // expected-error {{cannot use '__auto_type' as 'new' type}} +} + Index: test/Sema/exprs.c === --- test/Sema/exprs.c +++ test/Sema/exprs.c @@ -97,6 +97,7 @@ R = __alignof(P->x); // expected-error {{invalid application of 'alignof' to bit-field}} R = __alignof(P->y); // ok. R = sizeof(P->x); // expected-error {{invalid application of 'sizeof' to bit-field}} + __extension__ ({ R = (__typeof__(P->x)) 2; }); // expected-error {{invalid application of 'typeof' to bit-field}} return R; } Index: test/Sema/bitfield.c === --- test/Sema/bitfield.c +++ test/Sema/bitfield.c @@ -63,7 +63,8 @@ typedef signed Signed; struct Test5 { unsigned n : 2; } t5; -typedef __typeof__(t5.n) Unsigned; // Bitfield is unsigned +// Bitfield is unsigned +struct Test5 sometest5 = {-1}; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -1 to 3}} typedef __typeof__(+t5.n) Signed; // ... but promotes to signed. typedef __typeof__(t5.n + 0) Signed; // Arithmetic promotes. Index: test/Sema/auto-type.c === --- /dev/null +++ test/Sema/auto-type.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic -std=c11 + +__auto_type a = 5; // expected-warning {{'__auto_type' is a GNU extension}} +__extension__ __auto_type a1 = 5; +#pragma clang diagnostic ignored "-Wgnu-auto-type" +__auto_type b = 5.0; +__auto_type c = &b; +__auto_type d = (struct {int a;}) {5}; +_Static_assert(__builtin_types_compatible_p(__typeof(a), int), ""); +__auto_type e = e; // expected-error {{variable 'e' declared with '__auto_type' type cannot appear in its own initializer}} + +struct s { __auto_type a; }; // expected-error {{'__auto_type' not allowed in struct member}} + +__auto_type f = 1, g = 1.0; // expected-error {{'__auto_type' deduced as 'int' in declaration of 'f' and deduced as 'double' in declaration of 'g'}} + +__auto_type h() {} // expected-error {{'__auto_type' not allowed in function return type}} + +int i() { + struct bitfield { int field:2; }; + __auto_type j = (struct bitfield){1}.field; // expected-error {{cannot pass bit-field as __auto_type initializer in C}} + +} Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp === --- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp +++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp @@ -3,9 +3,9 @@ // FIXME: This is in p11 (?) in C++1y. void f() { - decl
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex updated this revision to Diff 37215. comex added a comment. Okay. http://reviews.llvm.org/D12686 Files: include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/Specifiers.h include/clang/Basic/TokenKinds.def include/clang/Sema/DeclSpec.h lib/AST/ASTContext.cpp lib/AST/ASTImporter.cpp lib/AST/ItaniumMangle.cpp lib/AST/MicrosoftMangle.cpp lib/AST/Type.cpp lib/AST/TypePrinter.cpp lib/Format/TokenAnnotator.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseTentative.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp test/Sema/auto-type.c test/Sema/bitfield.c test/Sema/exprs.c test/SemaCXX/auto-type-from-cxx.cpp Index: test/SemaCXX/auto-type-from-cxx.cpp === --- /dev/null +++ test/SemaCXX/auto-type-from-cxx.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s + +struct A { +operator __auto_type() {} // expected-error {{'__auto_type' not allowed in conversion function type}} +}; + +__auto_type a() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not '__auto_type'}} +template +__auto_type b() { return T::x; } // expected-error {{'__auto_type' not allowed in function return type}} +auto c() -> __auto_type { __builtin_unreachable(); } // expected-error {{'__auto_type' not allowed in function return type}} +int d() { + decltype(__auto_type) e = 1; // expected-error {{expected expression}} + auto _ = [](__auto_type f) {}; // expected-error {{'__auto_type' not allowed in lambda parameter}} + __auto_type g = 2; + struct BitField { int field:2; }; + __auto_type h = BitField{1}.field; // (should work from C++) + new __auto_type; // expected-error {{'__auto_type' not allowed in 'new' argument}} +} + Index: test/Sema/exprs.c === --- test/Sema/exprs.c +++ test/Sema/exprs.c @@ -97,6 +97,7 @@ R = __alignof(P->x); // expected-error {{invalid application of 'alignof' to bit-field}} R = __alignof(P->y); // ok. R = sizeof(P->x); // expected-error {{invalid application of 'sizeof' to bit-field}} + __extension__ ({ R = (__typeof__(P->x)) 2; }); // expected-error {{invalid application of 'typeof' to bit-field}} return R; } Index: test/Sema/bitfield.c === --- test/Sema/bitfield.c +++ test/Sema/bitfield.c @@ -63,7 +63,8 @@ typedef signed Signed; struct Test5 { unsigned n : 2; } t5; -typedef __typeof__(t5.n) Unsigned; // Bitfield is unsigned +// Bitfield is unsigned +struct Test5 sometest5 = {-1}; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -1 to 3}} typedef __typeof__(+t5.n) Signed; // ... but promotes to signed. typedef __typeof__(t5.n + 0) Signed; // Arithmetic promotes. Index: test/Sema/auto-type.c === --- /dev/null +++ test/Sema/auto-type.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic -std=c11 + +__auto_type a = 5; // expected-warning {{'__auto_type' is a GNU extension}} +__extension__ __auto_type a1 = 5; +#pragma clang diagnostic ignored "-Wgnu-auto-type" +__auto_type b = 5.0; +__auto_type c = &b; +__auto_type d = (struct {int a;}) {5}; +_Static_assert(__builtin_types_compatible_p(__typeof(a), int), ""); +__auto_type e = e; // expected-error {{variable 'e' declared with '__auto_type' type cannot appear in its own initializer}} + +struct s { __auto_type a; }; // expected-error {{'__auto_type' not allowed in struct member}} + +__auto_type f = 1, g = 1.0; // expected-error {{'__auto_type' deduced as 'int' in declaration of 'f' and deduced as 'double' in declaration of 'g'}} + +__auto_type h() {} // expected-error {{'__auto_type' not allowed in function return type}} + +int i() { + struct bitfield { int field:2; }; + __auto_type j = (struct bitfield){1}.field; // expected-error {{cannot pass bit-field as __auto_type initializer in C}} + +} Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp === --- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp +++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp @@ -3,9 +3,9 @@ // FIXME: This is in p11 (?) in C++1y. void f() { - decltype(auto) a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}} - if (decltype(auto) b = b) {} // exp
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex added inline comments. Comment at: lib/Sema/SemaType.cpp:2654-2655 @@ -2648,4 +2653,4 @@ case Declarator::ConversionIdContext: if (!SemaRef.getLangOpts().CPlusPlus14) -Error = 12; // conversion-type-id +Error = 14; // conversion-type-id break; rsmith wrote: > Do you really want to allow `__auto_type` here? This is inconsistent with > what you do for return types. Also a mistake. Comment at: test/SemaCXX/auto-type-from-cxx.cpp:14 @@ +13,3 @@ + auto _ = [](__auto_type f) {}; // expected-error {{'__auto_type' not allowed in lambda parameter}} + __auto_type g = 2; + struct BitField { int field:2; }; thakis wrote: > Shouldn't this say "warning: __auto_type is a gnu extension" (since this uses > -std=c++14, not -std=gnu++14)? Hmm... when I added `ext_auto_type` to the .td, I didn't notice the difference between Extension and ExtWarn. Since the patch currently uses Extension, it won't warn by default, but will with `-pedantic`, `-Wgnu`, or `-Wgnu-auto-type`. The C test uses `-pedantic` so it gets the warning. Is there an explicit policy on which extensions should be ExtWarn? Looking at the rest of that file, ExtWarns seem to be mostly either (a) standardized extensions (which will warn if `-std` is too early) and (b) 'extensions' that are more like "Clang will accept your buggy code" than features. Most GNU extensions are just Extension, so I think it makes sense to do the same for `__auto_type`. I could update the C++ test to add `-pedantic`, but arguably it makes more sense to test the fact that the warning is not emitted by default. http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex added inline comments. Comment at: lib/Sema/SemaType.cpp:2675-2678 @@ -2671,5 +2674,6 @@ break; case Declarator::ConversionIdContext: - if (!SemaRef.getLangOpts().CPlusPlus14) -Error = 12; // conversion-type-id + if (!SemaRef.getLangOpts().CPlusPlus14 || + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type) +Error = 14; // conversion-type-id break; (Clarification: The "also a mistake" comment was meant to be submitted earlier, but was left in the Phabricator draft state; I already fixed this.) http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex added inline comments. Comment at: test/SemaCXX/auto-type-from-cxx.cpp:14 @@ +13,3 @@ + auto _ = [](__auto_type f) {}; // expected-error {{'__auto_type' not allowed in lambda parameter}} + __auto_type g = 2; + struct BitField { int field:2; }; thakis wrote: > comex wrote: > > thakis wrote: > > > Shouldn't this say "warning: __auto_type is a gnu extension" (since this > > > uses -std=c++14, not -std=gnu++14)? > > Hmm... when I added `ext_auto_type` to the .td, I didn't notice the > > difference between Extension and ExtWarn. Since the patch currently uses > > Extension, it won't warn by default, but will with `-pedantic`, `-Wgnu`, or > > `-Wgnu-auto-type`. The C test uses `-pedantic` so it gets the warning. > > > > Is there an explicit policy on which extensions should be ExtWarn? Looking > > at the rest of that file, ExtWarns seem to be mostly either (a) > > standardized extensions (which will warn if `-std` is too early) and (b) > > 'extensions' that are more like "Clang will accept your buggy code" than > > features. Most GNU extensions are just Extension, so I think it makes > > sense to do the same for `__auto_type`. > > > > I could update the C++ test to add `-pedantic`, but arguably it makes more > > sense to test the fact that the warning is not emitted by default. > I'm not sure either. `typeof` warns with -std=c++14 but not with > -std=gnu++14. From a user perspective, this makes sense to me: I want to > write standard c++ and I want the compiler to help me with that, but I don't > want to get all the pedantic warnings that -pedantic entails. For example, > consider using clang-cl to build Windows code, and wanting MSVC to be able to > build said Windows code too. (This can of course go wrong with standard C++ > too, but in that case I'm running into MSVC bugs which will eventually be > fixed.) So if it's possible to match how typeof works, I think that'd be > good. If it's not possible, this wouldn't be the only GNU extension allowed > in -std=c++14 mode though, so it's not a big thing. As far as I can tell, `typeof` doesn't warn at all. In standard mode it's an *error* because `typeof` is treated as a normal identifier (so that code that uses it as such doesn't break), but if you use the reserved-namespace keyword `__typeof`, there is no warning even with `-Weverything`. http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex added a comment. One more ping. As far as I know, everything has been addressed. http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex added a comment. (Ping? I verified yesterday that the patch still applies and passes regression tests.) http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex updated this revision to Diff 39838. comex marked 16 inline comments as done. http://reviews.llvm.org/D12686 Files: include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/Specifiers.h include/clang/Basic/TokenKinds.def include/clang/Sema/DeclSpec.h lib/AST/ASTContext.cpp lib/AST/ASTImporter.cpp lib/AST/ItaniumMangle.cpp lib/AST/MicrosoftMangle.cpp lib/AST/Type.cpp lib/AST/TypePrinter.cpp lib/Format/TokenAnnotator.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseTentative.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp test/Sema/auto-type.c test/Sema/bitfield.c test/Sema/exprs.c test/SemaCXX/auto-type-from-cxx.cpp test/SemaCXX/cxx98-compat.cpp Index: test/SemaCXX/cxx98-compat.cpp === --- test/SemaCXX/cxx98-compat.cpp +++ test/SemaCXX/cxx98-compat.cpp @@ -100,6 +100,9 @@ }; auto f() -> int; // expected-warning {{trailing return types are incompatible with C++98}} +#ifdef CXX14COMPAT +auto ff() { return 5; } // expected-warning {{'auto' type specifier is incompatible with C++98}} +#endif void RangeFor() { int xs[] = {1, 2, 3}; Index: test/SemaCXX/auto-type-from-cxx.cpp === --- /dev/null +++ test/SemaCXX/auto-type-from-cxx.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s + +struct A { +operator __auto_type() {} // expected-error {{'__auto_type' not allowed in conversion function type}} +}; + +__auto_type a() -> int; // expected-error {{'__auto_type' not allowed in function return type}} +template +__auto_type b() { return T::x; } // expected-error {{'__auto_type' not allowed in function return type}} +auto c() -> __auto_type { __builtin_unreachable(); } // expected-error {{'__auto_type' not allowed in function return type}} +int d() { + decltype(__auto_type) e = 1; // expected-error {{expected expression}} + auto _ = [](__auto_type f) {}; // expected-error {{'__auto_type' not allowed in lambda parameter}} + __auto_type g = 2; + struct BitField { int field:2; }; + __auto_type h = BitField{1}.field; // (should work from C++) + new __auto_type; // expected-error {{'__auto_type' not allowed in type allocated by 'new'}} +} + Index: test/Sema/exprs.c === --- test/Sema/exprs.c +++ test/Sema/exprs.c @@ -97,6 +97,7 @@ R = __alignof(P->x); // expected-error {{invalid application of 'alignof' to bit-field}} R = __alignof(P->y); // ok. R = sizeof(P->x); // expected-error {{invalid application of 'sizeof' to bit-field}} + __extension__ ({ R = (__typeof__(P->x)) 2; }); // expected-error {{invalid application of 'typeof' to bit-field}} return R; } Index: test/Sema/bitfield.c === --- test/Sema/bitfield.c +++ test/Sema/bitfield.c @@ -63,7 +63,8 @@ typedef signed Signed; struct Test5 { unsigned n : 2; } t5; -typedef __typeof__(t5.n) Unsigned; // Bitfield is unsigned +// Bitfield is unsigned +struct Test5 sometest5 = {-1}; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -1 to 3}} typedef __typeof__(+t5.n) Signed; // ... but promotes to signed. typedef __typeof__(t5.n + 0) Signed; // Arithmetic promotes. Index: test/Sema/auto-type.c === --- /dev/null +++ test/Sema/auto-type.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic -std=c11 + +__auto_type a = 5; // expected-warning {{'__auto_type' is a GNU extension}} +__extension__ __auto_type a1 = 5; +#pragma clang diagnostic ignored "-Wgnu-auto-type" +__auto_type b = 5.0; +__auto_type c = &b; +__auto_type d = (struct {int a;}) {5}; +_Static_assert(__builtin_types_compatible_p(__typeof(a), int), ""); +__auto_type e = e; // expected-error {{variable 'e' declared with '__auto_type' type cannot appear in its own initializer}} + +struct s { __auto_type a; }; // expected-error {{'__auto_type' not allowed in struct member}} + +__auto_type f = 1, g = 1.0; // expected-error {{'__auto_type' deduced as 'int' in declaration of 'f' and deduced as 'double' in declaration of 'g'}} + +__auto_type h() {} // expected-error {{'__auto_type' not allowed in function return type}} + +int i() { + struct bitfield { int field:2; }; + __auto_type j = (struct bitfield){1}.field; // expected-error {{cannot pass
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex added a comment. Addressed comments. Thanks, rsmith! Comment at: lib/Sema/SemaType.cpp:3756-3760 @@ -3743,2 +3755,7 @@ } +} else if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type) { + S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::err_auto_not_allowed) +<< 2 << 13 << D.getDeclSpec().getSourceRange(); + D.setInvalidType(true); } rsmith wrote: > Please deal with this in the "checking for auto" block at the top rather than > repeating the diagnostic code here with magic numbers; maybe change > > (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) { > > to > > (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator() || > D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)) { > > up there. For the sake of clarity, I removed that whole bit from the if condition instead and moved the C++11 test down to where it sets `Error`. Two bits of fallout from this: - `typedef decltype(auto) f();` gets diagnosed there rather than later with a different error; I updated the test, since both errors seem reasonable. - A bug is fixed where definitions like `auto f() { return 5; }` were not being caught with `-std=c++14 -Wc++98-compat`. I updated the c++98-compat test to add this case. http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12686: Add support for GCC's '__auto_type' extension.
comex added a comment. I don't have SVN access. If you want to commit it, feel free to remove that comment, or else I'll update the diff tomorrow. I just tried the test case in 25449 and it now gives a proper error rather than crashing. (Though when trying to reduce a test failure I was encountering, I did find yet another pre-existing crasher, which doesn't seem to be related to the code being changed here. I should definitely check which of the crashers I found have existing bug reports and file the rest.) http://reviews.llvm.org/D12686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D15907: Allow various function attributes to be specified on Objective-C blocks too.
comex created this revision. comex added a subscriber: cfe-commits. Herald added a subscriber: aemerson. This mostly "just works" by adding Block to the subject list, but there is an issue with warnings in attribute handlers tied to the return type, which for blocks can be inferred. My solution to this is a bit ugly but seems to do the right thing. The list: always_inline, noinline, cold, hot, minsize, malloc, disable_tail_calls, noalias, noduplicate, nonnull, returns_nonnull, optnone. nonnull already partially worked on blocks, but fix applying it to parameters on them; also, improve the error message and add additional tests. Most of these attributes only make sense when the target of a function call is known; since blocks are always called indirectly via pointers, these will only work if the optimizer is able to replace the indirect calls with direct calls (ergo not at all at -O0). However, this can still be useful in practice. For now, all of them only apply to the block implementation function itself, as opposed to the copy and dispose helpers. For those it might make sense to propagate always_inline in particular, or perhaps to just add some explicit syntax for putting attributes on them, but it's not essential. Incidentally, for some of these attributes and some not included, such as returns_nonnull, printf, warn_unused_result, etc., it would be somewhat useful and more principled to allow them as part of function types rather than just functions themselves, for the sake of both standard function pointer calls and blocks. Currently only a handful of attributes can be used on types: noreturn, ns_returns_retained, regparm, and calling convention. However, that would be a larger change and orthogonal to this patch. http://reviews.llvm.org/D15907 Files: include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/Parser.h include/clang/Sema/AttributeList.h include/clang/Sema/Sema.h lib/Parse/ParseExpr.cpp lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaExpr.cpp lib/Sema/TreeTransform.h test/CXX/dcl.dcl/dcl.attr/dcl.attr.depend/p1.cpp test/CodeGen/always-inline.c test/CodeGen/attr-disable-tail-calls.c test/CodeGen/attr-noinline.c test/CodeGen/attr-optnone.c test/CodeGen/nonnull.c test/Parser/cxx0x-attributes.cpp test/Sema/attr-capabilities.c test/Sema/attr-coldhot.c test/Sema/attr-disable-tail-calls.c test/Sema/attr-malloc.c test/Sema/attr-minsize.c test/Sema/attr-noinline.c test/Sema/nonnull.c test/SemaObjC/attr-cf_returns.m test/SemaObjC/objcbridge-attribute-arc.m test/SemaObjC/objcbridge-attribute.m utils/TableGen/ClangAttrEmitter.cpp Index: utils/TableGen/ClangAttrEmitter.cpp === --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -2363,10 +2363,12 @@ case GenericRecord: return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : " "ExpectedStructOrUnion)"; +case Func | Block: return "ExpectedFunctionOrBlock"; case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock"; case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass"; case Func | Param: case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter"; +case Func | ObjCMethod | Block | Param: return "ExpectedFunctionMethodBlockOrParameter"; case Func | ObjCMethod: return "ExpectedFunctionOrMethod"; case Func | Var: return "ExpectedVariableOrFunction"; Index: test/SemaObjC/objcbridge-attribute.m === --- test/SemaObjC/objcbridge-attribute.m +++ test/SemaObjC/objcbridge-attribute.m @@ -38,7 +38,7 @@ @interface I { - __attribute__((objc_bridge(NSError))) void * color; // expected-error {{'objc_bridge' attribute only applies to structs, unions, and typedefs}}; + __attribute__((objc_bridge(NSError))) void * color; // expected-error {{'objc_bridge' attribute only applies to structs, unions and typedefs}}; } @end Index: test/SemaObjC/objcbridge-attribute-arc.m === --- test/SemaObjC/objcbridge-attribute-arc.m +++ test/SemaObjC/objcbridge-attribute-arc.m @@ -32,7 +32,7 @@ @interface I { - __attribute__((objc_bridge(NSError))) void * color; // expected-error {{'objc_bridge' attribute only applies to structs, unions, and typedefs}}; + __attribute__((objc_bridge(NSError))) void * color; // expected-error {{'objc_bridge' attribute only applies to structs, unions and typedefs}}; } @end Index: test/SemaObjC/attr-cf_returns.m === --- test/SemaObjC/attr-cf_returns.m +++ test/SemaObjC/attr-cf_returns.m @@ -10,8 +10,8 @@ #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) #define CF_RETURNS_NOT_RETAINED __attribute__(
Re: [PATCH] D15907: Allow various function attributes to be specified on Objective-C blocks too.
comex added reviewers: aaron.ballman, rsmith. comex added a comment. Ping, and adding potential reviewers like I was supposed to do in the first place. http://reviews.llvm.org/D15907 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D15406: Add warning for attribute-cleanup on function parameter.
comex created this revision. comex added a subscriber: cfe-commits. When a function parameter is declared `__attribute__((cleanup))`, neither Clang nor GCC actually executes the cleanup function, but Clang didn't warn about it. For the sake of compatibility, add a warning rather than making the attribute actually work. http://reviews.llvm.org/D15406 Files: lib/Sema/SemaDeclAttr.cpp test/Sema/attr-cleanup.c Index: test/Sema/attr-cleanup.c === --- test/Sema/attr-cleanup.c +++ test/Sema/attr-cleanup.c @@ -46,3 +46,5 @@ void t6(void) { int i __attribute__((cleanup((void *)0))); // expected-error {{'cleanup' argument is not a function}} } + +void t7(__attribute__((cleanup(c4))) int a) {} // expected-warning {{'cleanup' attribute ignored}} Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -2595,7 +2595,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { VarDecl *VD = cast(D); - if (!VD->hasLocalStorage()) { + if (!VD->hasLocalStorage() || isa(VD)) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); return; } Index: test/Sema/attr-cleanup.c === --- test/Sema/attr-cleanup.c +++ test/Sema/attr-cleanup.c @@ -46,3 +46,5 @@ void t6(void) { int i __attribute__((cleanup((void *)0))); // expected-error {{'cleanup' argument is not a function}} } + +void t7(__attribute__((cleanup(c4))) int a) {} // expected-warning {{'cleanup' attribute ignored}} Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -2595,7 +2595,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { VarDecl *VD = cast(D); - if (!VD->hasLocalStorage()) { + if (!VD->hasLocalStorage() || isa(VD)) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); return; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits