r318900 - Do not perform the analysis based warning if the warnings are ignored
Author: ogoffart Date: Thu Nov 23 00:15:22 2017 New Revision: 318900 URL: http://llvm.org/viewvc/llvm-project?rev=318900&view=rev Log: Do not perform the analysis based warning if the warnings are ignored This saves some cycles when compiling with "-w". (Also fix a potential crash on invalid code for tools that tries to recover from some errors, because analysis might compute the CFG which crashes if the code contains invalid declaration. This does not happen normally with because we also don't perform these analysis if there was an error.) Differential Revision: https://reviews.llvm.org/D40242 Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp cfe/trunk/unittests/Tooling/ToolingTest.cpp Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=318900&r1=318899&r2=318900&view=diff == --- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original) +++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Thu Nov 23 00:15:22 2017 @@ -2080,10 +2080,10 @@ AnalysisBasedWarnings::IssueWarnings(sem // time. DiagnosticsEngine &Diags = S.getDiagnostics(); - // Do not do any analysis for declarations in system headers if we are - // going to just ignore them. - if (Diags.getSuppressSystemWarnings() && - S.SourceMgr.isInSystemHeader(D->getLocation())) + // Do not do any analysis if we are going to just ignore them. + if (Diags.getIgnoreAllWarnings() || + (Diags.getSuppressSystemWarnings() && + S.SourceMgr.isInSystemHeader(D->getLocation( return; // For code in dependent contexts, we'll do this at instantiation time. Modified: cfe/trunk/unittests/Tooling/ToolingTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ToolingTest.cpp?rev=318900&r1=318899&r2=318900&view=diff == --- cfe/trunk/unittests/Tooling/ToolingTest.cpp (original) +++ cfe/trunk/unittests/Tooling/ToolingTest.cpp Thu Nov 23 00:15:22 2017 @@ -564,5 +564,31 @@ TEST(ClangToolTest, InjectDiagnosticCons } #endif +TEST(runToolOnCode, TestResetDiagnostics) { + // This is a tool that resets the diagnostic during the compilation. + struct ResetDiagnosticAction : public clang::ASTFrontendAction { +std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, + StringRef) override { + struct Consumer : public clang::ASTConsumer { +bool HandleTopLevelDecl(clang::DeclGroupRef D) override { + auto &Diags = (*D.begin())->getASTContext().getDiagnostics(); + // Ignore any error + Diags.Reset(); + // Disable warnings because computing the CFG might crash. + Diags.setIgnoreAllWarnings(true); + return true; +} + }; + return llvm::make_unique(); +} + }; + + // Should not crash + EXPECT_FALSE( + runToolOnCode(new ResetDiagnosticAction, +"struct Foo { Foo(int); ~Foo(); struct Fwd _fwd; };" +"void func() { long x; Foo f(x); }")); +} + } // end namespace tooling } // end namespace clang ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 1b04bdc - [SEH] capture 'this'
Author: Olivier Goffart Date: 2021-03-01T11:57:35+01:00 New Revision: 1b04bdc2f3ffaa7a0e1e3dbdc3a0cd08f0b9a4ce URL: https://github.com/llvm/llvm-project/commit/1b04bdc2f3ffaa7a0e1e3dbdc3a0cd08f0b9a4ce DIFF: https://github.com/llvm/llvm-project/commit/1b04bdc2f3ffaa7a0e1e3dbdc3a0cd08f0b9a4ce.diff LOG: [SEH] capture 'this' Simply make sure that the CodeGenFunction::CXXThisValue and CXXABIThisValue are correctly initialized to the recovered value. For lambda capture, we also need to make sure to fill the LambdaCaptureFields Differential Revision: https://reviews.llvm.org/D97534 Added: Modified: clang/lib/CodeGen/CGException.cpp clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp Removed: diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 7a64963183bc..ce8b42a8c63f 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1702,10 +1702,8 @@ struct CaptureFinder : ConstStmtVisitor { void VisitDeclRefExpr(const DeclRefExpr *E) { // If this is already a capture, just make sure we capture 'this'. -if (E->refersToEnclosingVariableOrCapture()) { +if (E->refersToEnclosingVariableOrCapture()) Captures.insert(ParentThis); - return; -} const auto *D = dyn_cast(E->getDecl()); if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage()) @@ -1865,11 +1863,6 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, // Create llvm.localrecover calls for all captures. for (const VarDecl *VD : Finder.Captures) { -if (isa(VD)) { - CGM.ErrorUnsupported(VD, "'this' captured by SEH"); - CXXThisValue = llvm::UndefValue::get(ConvertTypeForMem(VD->getType())); - continue; -} if (VD->getType()->isVariablyModifiedType()) { CGM.ErrorUnsupported(VD, "VLA captured by SEH"); continue; @@ -1877,6 +1870,12 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, assert((isa(VD) || VD->isLocalVarDeclOrParm()) && "captured non-local variable"); +auto L = ParentCGF.LambdaCaptureFields.find(VD); +if (L != ParentCGF.LambdaCaptureFields.end()) { + LambdaCaptureFields[VD] = L->second; + continue; +} + // If this decl hasn't been declared yet, it will be declared in the // OutlinedStmt. auto I = ParentCGF.LocalDeclMap.find(VD); @@ -1884,8 +1883,14 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, continue; Address ParentVar = I->second; -setAddrOfLocalVar( -VD, recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP)); +Address Recovered = +recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP); +setAddrOfLocalVar(VD, Recovered); + +if (isa(VD)) { + CXXThisValue = Builder.CreateLoad(Recovered, "this"); + CXXABIThisValue = CXXThisValue; +} } if (Finder.SEHCodeSlot.isValid()) { diff --git a/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp b/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp index ac33dbff0b1c..f6cca8eda9d9 100644 --- a/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp +++ b/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp @@ -39,13 +39,13 @@ void S::test_method() { int l1 = 13; __try { might_crash(); - } __except(basic_filter(l1)) { -// FIXME: Test capturing 'this' and 'm1'. + } __except (basic_filter(l1, m1)) { } } // CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(%struct.S* {{[^,]*}} %this) -// CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]]) +// CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]], %struct.S** %[[this_addr:[^, ]*]]) +// CHECK: store %struct.S* %this, %struct.S** %[[this_addr]], align 8 // CHECK: store i32 13, i32* %[[l1_addr]], align 4 // CHECK: invoke void @might_crash() @@ -53,8 +53,45 @@ void S::test_method() { // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer) // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0) // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32* +// CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 1) +// CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %struct.S** +// CHECK: %[[this:[^ ]*]] = load %struct.S*, %struct.S** %[[this_ptr]], align 8 +// CHECK: %[[m1_ptr:[^ ]*]] = getelementptr inbounds %struct.S, %struct.S* %[[this]], i32 0, i32 0 +// CHECK: %[[m1:[^ ]*]] = load i32, i32* %[[m1_ptr]] // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]] -// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]]) +// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]], i32
[clang] 5baea05 - [SEH] Fix capture of this in lambda functions
Author: Olivier Goffart Date: 2021-03-11T09:12:42+01:00 New Revision: 5baea0560160a693b19022c5d0ba637b6b46b2d8 URL: https://github.com/llvm/llvm-project/commit/5baea0560160a693b19022c5d0ba637b6b46b2d8 DIFF: https://github.com/llvm/llvm-project/commit/5baea0560160a693b19022c5d0ba637b6b46b2d8.diff LOG: [SEH] Fix capture of this in lambda functions Commit 1b04bdc2f3ffaa7a0e1e3dbdc3a0cd08f0b9a4ce added support for capturing the 'this' pointer in a SEH context (__finally or __except), But the case in which the 'this' pointer is part of a lambda capture was not handled properly Differential Revision: https://reviews.llvm.org/D97687 Added: Modified: clang/lib/CodeGen/CGException.cpp clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp Removed: diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 97e2a3a4b69a..5ac037cd9db9 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1879,8 +1879,24 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, setAddrOfLocalVar(VD, Recovered); if (isa(VD)) { - CXXThisValue = Builder.CreateLoad(Recovered, "this"); - CXXABIThisValue = CXXThisValue; + CXXABIThisAlignment = ParentCGF.CXXABIThisAlignment; + CXXThisAlignment = ParentCGF.CXXThisAlignment; + CXXABIThisValue = Builder.CreateLoad(Recovered, "this"); + if (ParentCGF.LambdaThisCaptureField) { +LambdaThisCaptureField = ParentCGF.LambdaThisCaptureField; +// We are in a lambda function where "this" is captured so the +// CXXThisValue need to be loaded from the lambda capture +LValue ThisFieldLValue = +EmitLValueForLambdaField(LambdaThisCaptureField); +if (!LambdaThisCaptureField->getType()->isPointerType()) { + CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); +} else { + CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation()) + .getScalarVal(); +} + } else { +CXXThisValue = CXXABIThisValue; + } } } @@ -1949,6 +1965,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args, OutlinedStmt->getBeginLoc(), OutlinedStmt->getBeginLoc()); CurSEHParent = ParentCGF.CurSEHParent; + CurCodeDecl = ParentCGF.CurCodeDecl; CGM.SetInternalFunctionAttributes(GlobalDecl(), CurFn, FnInfo); EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter); diff --git a/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp b/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp index f6cca8eda9d9..6b5c27097cbd 100644 --- a/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp +++ b/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp @@ -123,3 +123,25 @@ void test_lambda() { // CHECK: %[[l1_ref:[^ ]*]] = load i32*, i32** %[[l1_ref_ptr]] // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ref]] // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]], i32 %[[l2]]) + +struct U { + void this_in_lambda(); +}; + +void U::this_in_lambda() { + auto lambda = [=]() { +__try { + might_crash(); +} __except (basic_filter(0, this)) { +} + }; + lambda(); +} + +// CHECK-LABEL: define internal i32 @"?filt$0@0@?R@?0??this_in_lambda@U@@QEAAXXZ@"(i8* %exception_pointers, i8* %frame_pointer) +// CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon.0*)* @"??R@?0??this_in_lambda@U@@QEAAXXZ@QEBA@XZ" to i8*), i8* %[[fp:[^ ]*]], i32 0) +// CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %class.anon.0** +// CHECK: %[[this:[^ ]*]] = load %class.anon.0*, %class.anon.0** %[[this_ptr]], align 8 +// CHECK: %[[actual_this_ptr:[^ ]*]] = getelementptr inbounds %class.anon.0, %class.anon.0* %[[this]], i32 0, i32 0 +// CHECK: %[[actual_this:[^ ]*]] = load %struct.U*, %struct.U** %[[actual_this_ptr]], align 8 +// CHECK: call i32 (i32, ...) @basic_filter(i32 0, %struct.U* %[[actual_this]]) ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11
ogoffart added a comment. Ping! https://reviews.llvm.org/D21502 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D23837: Fix colored diagnostics from tools
ogoffart created this revision. ogoffart added reviewers: bruno, dexonsmith, cfe-commits. Herald added a subscriber: klimek. r271042 changed the way the diagnostic arguments are parsed. It assumes that the diagnostics options were already parsed by the "Driver". For tools using clang::Tooling, the diagnostics argument were not parsed. https://reviews.llvm.org/D23837 Files: lib/Tooling/Tooling.cpp Index: lib/Tooling/Tooling.cpp === --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/Tooling.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ASTUnit.h" @@ -26,6 +27,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -241,6 +243,9 @@ Argv.push_back(Str.c_str()); const char *const BinaryName = Argv[0]; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + unsigned MissingArgIndex, MissingArgCount; + llvm::opt::InputArgList ParsedArgs = driver::createDriverOptTable()->ParseArgs(ArrayRef(Argv).slice(1), MissingArgIndex, MissingArgCount); + ParseDiagnosticArgs(*DiagOpts, ParsedArgs); TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( Index: lib/Tooling/Tooling.cpp === --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/Tooling.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ASTUnit.h" @@ -26,6 +27,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -241,6 +243,9 @@ Argv.push_back(Str.c_str()); const char *const BinaryName = Argv[0]; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + unsigned MissingArgIndex, MissingArgCount; + llvm::opt::InputArgList ParsedArgs = driver::createDriverOptTable()->ParseArgs(ArrayRef(Argv).slice(1), MissingArgIndex, MissingArgCount); + ParseDiagnosticArgs(*DiagOpts, ParsedArgs); TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D23837: Fix colored diagnostics from tools
ogoffart updated this revision to Diff 69221. ogoffart added a comment. Added a test. https://reviews.llvm.org/D23837 Files: lib/Tooling/Tooling.cpp unittests/Tooling/ToolingTest.cpp Index: unittests/Tooling/ToolingTest.cpp === --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -332,6 +332,47 @@ EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str())); } +struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction { + CheckColoredDiagnosticsAction(bool ShouldShowColor) + : ShouldShowColor(ShouldShowColor) {} + std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, + StringRef) override { +if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor) + Compiler.getDiagnostics().Report( + Compiler.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Fatal, + "getDiagnosticOpts().ShowColors != ShouldShowColor")); +return llvm::make_unique(); + } + +private: + bool ShouldShowColor = true; +}; + +TEST(runToolOnCodeWithArgs, DiagnosticsColor) { + // Defaults to showing the colors. + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", {})); + // Check that this test would fail if ShowColors is not what it should. + EXPECT_FALSE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "", {})); + + // Last argument wins. + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", +{"-fcolor-diagnostics"})); + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), +"", {"-fno-color-diagnostics"})); + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", +{"-fno-color-diagnostics", "-fcolor-diagnostics"})); + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "", +{"-fcolor-diagnostics", "-fno-color-diagnostics"})); + EXPECT_TRUE(runToolOnCodeWithArgs( + new CheckColoredDiagnosticsAction(true), "", + {"-fno-color-diagnostics", "-fdiagnostics-color=always"})); +} + TEST(ClangToolTest, ArgumentAdjusters) { FixedCompilationDatabase Compilations("/", std::vector()); Index: lib/Tooling/Tooling.cpp === --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/Tooling.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ASTUnit.h" @@ -26,6 +27,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -241,6 +243,12 @@ Argv.push_back(Str.c_str()); const char *const BinaryName = Argv[0]; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + unsigned MissingArgIndex, MissingArgCount; + llvm::opt::InputArgList ParsedArgs = + driver::createDriverOptTable()->ParseArgs( + ArrayRef(Argv).slice(1), MissingArgIndex, + MissingArgCount); + ParseDiagnosticArgs(*DiagOpts, ParsedArgs); TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( Index: unittests/Tooling/ToolingTest.cpp === --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -332,6 +332,47 @@ EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str())); } +struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction { + CheckColoredDiagnosticsAction(bool ShouldShowColor) + : ShouldShowColor(ShouldShowColor) {} + std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, + StringRef) override { +if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor) + Compiler.getDiagnostics().Report( + Compiler.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Fatal, + "getDiagnosticOpts().ShowColors != ShouldShowColor")); +return llvm::make_unique(); + } + +private: + bool ShouldShowColor = true; +}; + +TEST(runToolOnCodeWithArgs, DiagnosticsColor) { + // Defaults to showing the colors. + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", {})); + // Check that this test would fail if ShowColors is not what it should. + EXPECT_FALSE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "", {})); + + // Last argument wins. + EXP
Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11
ogoffart updated this revision to Diff 69223. ogoffart added a comment. Made the requested changes https://reviews.llvm.org/D21502 Files: lib/Parse/ParseCXXInlineMethods.cpp test/CodeCompletion/ctor-initializer.cpp Index: test/CodeCompletion/ctor-initializer.cpp === --- test/CodeCompletion/ctor-initializer.cpp +++ test/CodeCompletion/ctor-initializer.cpp @@ -1,11 +1,13 @@ struct Base1 { Base1() : {} - // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>) // CHECK-CC1: COMPLETION: Pattern : member2(<#args#> Base1(int) : member1(123), {} - // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:7:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>) // CHECK-CC2: COMPLETION: Pattern : member2(<#args#> @@ -21,21 +23,40 @@ }; Derived::Derived() : {} -// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>) // CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>) Derived::Derived(int) try : { } catch (...) { } -// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:28:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s // CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>) // CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>) Derived::Derived(float) try : Base1(), { } catch (...) { } -// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:35:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s // CHECK-CC5-NOT: COMPLETION: Pattern : Base1(<#args#>) // CHECK-CC5: COMPLETION: Pattern : deriv1(<#args#>) + +struct A { + A() : , member2() {} + // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s + // CHECK-CC6: COMPLETION: Pattern : member1(<#args#> + int member1, member2; +}; + +struct B { + B() : member2() {} + // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s + // CHECK-CC7: COMPLETION: Pattern : member1(<#args#> + int member1, member2; +}; Index: lib/Parse/ParseCXXInlineMethods.cpp === --- lib/Parse/ParseCXXInlineMethods.cpp +++ lib/Parse/ParseCXXInlineMethods.cpp @@ -832,22 +832,30 @@ } } - if (Tok.isOneOf(tok::identifier, tok::kw_template)) { + if (Tok.is(tok::identifier)) { Toks.push_back(Tok); ConsumeToken(); - } else if (Tok.is(tok::code_completion)) { -Toks.push_back(Tok); -ConsumeCodeCompletionToken(); -// Consume the rest of the initializers permissively. -// FIXME: We should be able to perform code-completion here even if -//there isn't a subsequent '{' token. -MightBeTemplateArgument = true; -break; } else { break; } } while (Tok.is(tok::coloncolon)); +if (Tok.is(tok::code_completion)) { + Toks.push_back(Tok); + ConsumeCodeCompletionToken(); + if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype)) { +// Could be the start of another member initializer (the ',' has not +// been written yet) +continue; + } +} + +if (Tok.is(tok::comma)) { + // The initialization is missing, we'll diagnose i
Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11
ogoffart added a comment. Regarding this: struct Foo { Foo() : some_long_x(0), some_| {} int some_long_x, some_long_y; }; That should work fine because the token before the { is the code completion token, not an identifier. This is basicaly tested by the test with CHECK-CC2. However, this does not work because if the completion is within an identifier, the Lexer will abort by calling cutOffLexing from Lexer::LexIdentifier https://reviews.llvm.org/D21502 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D23837: Fix colored diagnostics from tools
ogoffart updated this revision to Diff 69225. ogoffart added a comment. This new patch make sure the test run fine as part of the testsuite, where the output is not a terminal and the color are disabled by default https://reviews.llvm.org/D23837 Files: lib/Tooling/Tooling.cpp unittests/Tooling/ToolingTest.cpp Index: unittests/Tooling/ToolingTest.cpp === --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -332,6 +332,44 @@ EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str())); } +struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction { + CheckColoredDiagnosticsAction(bool ShouldShowColor) + : ShouldShowColor(ShouldShowColor) {} + std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, + StringRef) override { +if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor) + Compiler.getDiagnostics().Report( + Compiler.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Fatal, + "getDiagnosticOpts().ShowColors != ShouldShowColor")); +return llvm::make_unique(); + } + +private: + bool ShouldShowColor = true; +}; + +TEST(runToolOnCodeWithArgs, DiagnosticsColor) { + + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", +{"-fcolor-diagnostics"})); + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), +"", {"-fno-color-diagnostics"})); + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", +{"-fno-color-diagnostics", "-fcolor-diagnostics"})); + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "", +{"-fcolor-diagnostics", "-fno-color-diagnostics"})); + EXPECT_TRUE(runToolOnCodeWithArgs( + new CheckColoredDiagnosticsAction(true), "", + {"-fno-color-diagnostics", "-fdiagnostics-color=always"})); + + // Check that this test would fail if ShowColors is not what it should. + EXPECT_FALSE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), + "", {"-fcolor-diagnostics"})); +} + TEST(ClangToolTest, ArgumentAdjusters) { FixedCompilationDatabase Compilations("/", std::vector()); Index: lib/Tooling/Tooling.cpp === --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/Tooling.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ASTUnit.h" @@ -26,6 +27,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -241,6 +243,12 @@ Argv.push_back(Str.c_str()); const char *const BinaryName = Argv[0]; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + unsigned MissingArgIndex, MissingArgCount; + llvm::opt::InputArgList ParsedArgs = + driver::createDriverOptTable()->ParseArgs( + ArrayRef(Argv).slice(1), MissingArgIndex, + MissingArgCount); + ParseDiagnosticArgs(*DiagOpts, ParsedArgs); TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( Index: unittests/Tooling/ToolingTest.cpp === --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -332,6 +332,44 @@ EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str())); } +struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction { + CheckColoredDiagnosticsAction(bool ShouldShowColor) + : ShouldShowColor(ShouldShowColor) {} + std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, + StringRef) override { +if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor) + Compiler.getDiagnostics().Report( + Compiler.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Fatal, + "getDiagnosticOpts().ShowColors != ShouldShowColor")); +return llvm::make_unique(); + } + +private: + bool ShouldShowColor = true; +}; + +TEST(runToolOnCodeWithArgs, DiagnosticsColor) { + + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", +{"-fcolor-diagnostics"})); + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), +"", {"-fno-color-diagnostics"})); + EXPECT_TRUE( +
Re: [PATCH] D23837: Fix colored diagnostics from tools
ogoffart added a comment. Ping https://reviews.llvm.org/D23837 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11
ogoffart added a comment. ping https://reviews.llvm.org/D21502 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11
ogoffart added a comment. Ping https://reviews.llvm.org/D21502 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r280118 - Fix colored diagnostics from tools
Author: ogoffart Date: Tue Aug 30 12:42:29 2016 New Revision: 280118 URL: http://llvm.org/viewvc/llvm-project?rev=280118&view=rev Log: Fix colored diagnostics from tools r271042 changed the way the diagnostic arguments are parsed. It assumes that the diagnostics options were already parsed by the "Driver". For tools using clang::Tooling, the diagnostics argument were not parsed. Differential Revision: https://reviews.llvm.org/D23837 Modified: cfe/trunk/lib/Tooling/Tooling.cpp cfe/trunk/unittests/Tooling/ToolingTest.cpp Modified: cfe/trunk/lib/Tooling/Tooling.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Tooling.cpp?rev=280118&r1=280117&r2=280118&view=diff == --- cfe/trunk/lib/Tooling/Tooling.cpp (original) +++ cfe/trunk/lib/Tooling/Tooling.cpp Tue Aug 30 12:42:29 2016 @@ -15,6 +15,7 @@ #include "clang/Tooling/Tooling.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ASTUnit.h" @@ -26,6 +27,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -241,6 +243,12 @@ bool ToolInvocation::run() { Argv.push_back(Str.c_str()); const char *const BinaryName = Argv[0]; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + unsigned MissingArgIndex, MissingArgCount; + llvm::opt::InputArgList ParsedArgs = + driver::createDriverOptTable()->ParseArgs( + ArrayRef(Argv).slice(1), MissingArgIndex, + MissingArgCount); + ParseDiagnosticArgs(*DiagOpts, ParsedArgs); TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( Modified: cfe/trunk/unittests/Tooling/ToolingTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ToolingTest.cpp?rev=280118&r1=280117&r2=280118&view=diff == --- cfe/trunk/unittests/Tooling/ToolingTest.cpp (original) +++ cfe/trunk/unittests/Tooling/ToolingTest.cpp Tue Aug 30 12:42:29 2016 @@ -332,6 +332,44 @@ TEST(runToolOnCodeWithArgs, TestNoDepFil EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str())); } +struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction { + CheckColoredDiagnosticsAction(bool ShouldShowColor) + : ShouldShowColor(ShouldShowColor) {} + std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, + StringRef) override { +if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor) + Compiler.getDiagnostics().Report( + Compiler.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Fatal, + "getDiagnosticOpts().ShowColors != ShouldShowColor")); +return llvm::make_unique(); + } + +private: + bool ShouldShowColor = true; +}; + +TEST(runToolOnCodeWithArgs, DiagnosticsColor) { + + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", +{"-fcolor-diagnostics"})); + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), +"", {"-fno-color-diagnostics"})); + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", +{"-fno-color-diagnostics", "-fcolor-diagnostics"})); + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "", +{"-fcolor-diagnostics", "-fno-color-diagnostics"})); + EXPECT_TRUE(runToolOnCodeWithArgs( + new CheckColoredDiagnosticsAction(true), "", + {"-fno-color-diagnostics", "-fdiagnostics-color=always"})); + + // Check that this test would fail if ShowColors is not what it should. + EXPECT_FALSE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), + "", {"-fcolor-diagnostics"})); +} + TEST(ClangToolTest, ArgumentAdjusters) { FixedCompilationDatabase Compilations("/", std::vector()); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D23837: Fix colored diagnostics from tools
This revision was automatically updated to reflect the committed changes. Closed by commit rL280118: Fix colored diagnostics from tools (authored by ogoffart). Changed prior to commit: https://reviews.llvm.org/D23837?vs=69225&id=69725#toc Repository: rL LLVM https://reviews.llvm.org/D23837 Files: cfe/trunk/lib/Tooling/Tooling.cpp cfe/trunk/unittests/Tooling/ToolingTest.cpp Index: cfe/trunk/lib/Tooling/Tooling.cpp === --- cfe/trunk/lib/Tooling/Tooling.cpp +++ cfe/trunk/lib/Tooling/Tooling.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/Tooling.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ASTUnit.h" @@ -26,6 +27,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -241,6 +243,12 @@ Argv.push_back(Str.c_str()); const char *const BinaryName = Argv[0]; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + unsigned MissingArgIndex, MissingArgCount; + llvm::opt::InputArgList ParsedArgs = + driver::createDriverOptTable()->ParseArgs( + ArrayRef(Argv).slice(1), MissingArgIndex, + MissingArgCount); + ParseDiagnosticArgs(*DiagOpts, ParsedArgs); TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( Index: cfe/trunk/unittests/Tooling/ToolingTest.cpp === --- cfe/trunk/unittests/Tooling/ToolingTest.cpp +++ cfe/trunk/unittests/Tooling/ToolingTest.cpp @@ -332,6 +332,44 @@ EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str())); } +struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction { + CheckColoredDiagnosticsAction(bool ShouldShowColor) + : ShouldShowColor(ShouldShowColor) {} + std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, + StringRef) override { +if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor) + Compiler.getDiagnostics().Report( + Compiler.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Fatal, + "getDiagnosticOpts().ShowColors != ShouldShowColor")); +return llvm::make_unique(); + } + +private: + bool ShouldShowColor = true; +}; + +TEST(runToolOnCodeWithArgs, DiagnosticsColor) { + + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", +{"-fcolor-diagnostics"})); + EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), +"", {"-fno-color-diagnostics"})); + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", +{"-fno-color-diagnostics", "-fcolor-diagnostics"})); + EXPECT_TRUE( + runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "", +{"-fcolor-diagnostics", "-fno-color-diagnostics"})); + EXPECT_TRUE(runToolOnCodeWithArgs( + new CheckColoredDiagnosticsAction(true), "", + {"-fno-color-diagnostics", "-fdiagnostics-color=always"})); + + // Check that this test would fail if ShowColors is not what it should. + EXPECT_FALSE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), + "", {"-fcolor-diagnostics"})); +} + TEST(ClangToolTest, ArgumentAdjusters) { FixedCompilationDatabase Compilations("/", std::vector()); Index: cfe/trunk/lib/Tooling/Tooling.cpp === --- cfe/trunk/lib/Tooling/Tooling.cpp +++ cfe/trunk/lib/Tooling/Tooling.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/Tooling.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ASTUnit.h" @@ -26,6 +27,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -241,6 +243,12 @@ Argv.push_back(Str.c_str()); const char *const BinaryName = Argv[0]; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + unsigned MissingArgIndex, MissingArgCount; + llvm::opt::InputArgList ParsedArgs = + driver::createDriverOptTable()->ParseArgs( + ArrayRef(Argv).slice(1), MissingArgIndex, + MissingArgCount); + ParseDiagnosticArgs(*DiagOpts, ParsedArgs); TextDiagnosticPrinter Diagnosti
r307371 - Fix crash parsing invalid code
Author: ogoffart Date: Fri Jul 7 02:38:59 2017 New Revision: 307371 URL: http://llvm.org/viewvc/llvm-project?rev=307371&view=rev Log: Fix crash parsing invalid code The code in the test caused a crash with this backtrace: RecordLayoutBuilder.cpp:2934: const clang::ASTRecordLayout &clang::ASTContext::getASTRecordLayout(const clang::RecordDecl *) const: Assertion `!D->isInvalidDecl() && "Cannot get layout of invalid decl!"' failed. [...] #7 0x7f63963d845a __assert_fail_base (/usr/lib/libc.so.6+0x2c45a) #8 0x7f63963d84d2 (/usr/lib/libc.so.6+0x2c4d2) #9 0x7f63937a0631 clang::ASTContext::getASTRecordLayout(clang::RecordDecl const*) const /home/olivier/prog/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp:2935:3 #10 0x7f63937a1ad5 getFieldOffset(clang::ASTContext const&, clang::FieldDecl const*) /home/olivier/prog/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp:3057:37 #11 0x7f6391869f14 clang::Sema::RefersToMemberWithReducedAlignment(clang::Expr*, llvm::function_ref) /home/olivier/prog/llvm/tools/clang/lib/Sema/SemaChecking.cpp:12139:23 #12 0x7f639186a2f8 clang::Sema::CheckAddressOfPackedMember(clang::Expr*) /home/olivier/prog/llvm/tools/clang/lib/Sema/SemaChecking.cpp:12190:1 #13 0x7f6391a7a81c clang::Sema::CheckAddressOfOperand(clang::ActionResult&, clang::SourceLocation) /home/olivier/prog/llvm/tools/clang/lib/Sema/SemaExpr.cpp:1:10 #14 0x7f6391a7f5d2 clang::Sema::CreateBuiltinUnaryOp(clang::SourceLocation, clang::UnaryOperatorKind, clang::Expr*) /home/olivier/prog/llvm/tools/clang/lib/Sema/SemaExpr.cpp:11932:18 Fixing by bailing out for invalid classes. Differential Revision: https://reviews.llvm.org/D35108 Modified: cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/Sema/address-packed.c Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=307371&r1=307370&r2=307371&view=diff == --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Jul 7 02:38:59 2017 @@ -12097,6 +12097,8 @@ void Sema::RefersToMemberWithReducedAlig if (ME->isArrow()) BaseType = BaseType->getPointeeType(); RecordDecl *RD = BaseType->getAs()->getDecl(); +if (RD->isInvalidDecl()) + return; ValueDecl *MD = ME->getMemberDecl(); auto *FD = dyn_cast(MD); Modified: cfe/trunk/test/Sema/address-packed.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address-packed.c?rev=307371&r1=307370&r2=307371&view=diff == --- cfe/trunk/test/Sema/address-packed.c (original) +++ cfe/trunk/test/Sema/address-packed.c Fri Jul 7 02:38:59 2017 @@ -329,3 +329,12 @@ void g13(void) { uint32_t *p32; p32 = &a[0].x; // no-warning } + +struct Invalid0 { + void *x; + struct fwd f; // expected-error {{incomplete type}} expected-note {{forward declaration}} +} __attribute__((packed)); + +void *g14(struct Invalid0 *ivl) { + return &(ivl->x); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r308008 - Keep the IdentifierInfo in the Token for alternative operator keyword
Author: ogoffart Date: Fri Jul 14 02:23:40 2017 New Revision: 308008 URL: http://llvm.org/viewvc/llvm-project?rev=308008&view=rev Log: Keep the IdentifierInfo in the Token for alternative operator keyword The goal of this commit is to fix clang-format so it does not merge tokens when using the alternative spelling keywords. (eg: "not foo" should not become "notfoo") The problem is that Preprocessor::HandleIdentifier used to drop the identifier info from the token for these keyword. This means the first condition of TokenAnnotator::spaceRequiredBefore is not met. We could add explicit check for the spelling in that condition, but I think it is better to keep the IdentifierInfo and handle the operator keyword explicitly when needed. That actually leads to simpler code, and probably slightly more efficient as well. Another side effect of this change is that __identifier(and) will now work as one would expect, removing a FIXME from the MicrosoftExtensions.cpp test Differential Revision: https://reviews.llvm.org/D35172 Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h cfe/trunk/lib/Lex/PPDirectives.cpp cfe/trunk/lib/Lex/PPExpressions.cpp cfe/trunk/lib/Lex/Preprocessor.cpp cfe/trunk/test/Parser/MicrosoftExtensions.cpp cfe/trunk/test/Preprocessor/cxx_oper_keyword.cpp cfe/trunk/unittests/Format/FormatTest.cpp Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=308008&r1=308007&r2=308008&view=diff == --- cfe/trunk/include/clang/Basic/IdentifierTable.h (original) +++ cfe/trunk/include/clang/Basic/IdentifierTable.h Fri Jul 14 02:23:40 2017 @@ -272,10 +272,6 @@ public: /// this identifier is a C++ alternate representation of an operator. void setIsCPlusPlusOperatorKeyword(bool Val = true) { IsCPPOperatorKeyword = Val; -if (Val) - NeedsHandleIdentifier = true; -else - RecomputeNeedsHandleIdentifier(); } bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; } @@ -381,10 +377,9 @@ private: /// This method is very tied to the definition of HandleIdentifier. Any /// change to it should be reflected here. void RecomputeNeedsHandleIdentifier() { -NeedsHandleIdentifier = - (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() | - isExtensionToken() | isFutureCompatKeyword() || isOutOfDate() || - isModulesImport()); +NeedsHandleIdentifier = isPoisoned() || hasMacroDefinition() || +isExtensionToken() || isFutureCompatKeyword() || +isOutOfDate() || isModulesImport(); } }; Modified: cfe/trunk/lib/Lex/PPDirectives.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=308008&r1=308007&r2=308008&view=diff == --- cfe/trunk/lib/Lex/PPDirectives.cpp (original) +++ cfe/trunk/lib/Lex/PPDirectives.cpp Fri Jul 14 02:23:40 2017 @@ -220,26 +220,18 @@ bool Preprocessor::CheckMacroName(Token return Diag(MacroNameTok, diag::err_pp_missing_macro_name); IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); - if (!II) { -bool Invalid = false; -std::string Spelling = getSpelling(MacroNameTok, &Invalid); -if (Invalid) - return Diag(MacroNameTok, diag::err_pp_macro_not_identifier); -II = getIdentifierInfo(Spelling); - -if (!II->isCPlusPlusOperatorKeyword()) - return Diag(MacroNameTok, diag::err_pp_macro_not_identifier); + if (!II) +return Diag(MacroNameTok, diag::err_pp_macro_not_identifier); + if (II->isCPlusPlusOperatorKeyword()) { // C++ 2.5p2: Alternative tokens behave the same as its primary token // except for their spellings. Diag(MacroNameTok, getLangOpts().MicrosoftExt ? diag::ext_pp_operator_used_as_macro_name : diag::err_pp_operator_used_as_macro_name) << II << MacroNameTok.getKind(); - // Allow #defining |and| and friends for Microsoft compatibility or // recovery when legacy C headers are included in C++. -MacroNameTok.setIdentifierInfo(II); } if ((isDefineUndef != MU_Other) && II->getPPKeywordID() == tok::pp_defined) { Modified: cfe/trunk/lib/Lex/PPExpressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPExpressions.cpp?rev=308008&r1=308007&r2=308008&view=diff == --- cfe/trunk/lib/Lex/PPExpressions.cpp (original) +++ cfe/trunk/lib/Lex/PPExpressions.cpp Fri Jul 14 02:23:40 2017 @@ -237,35 +237,32 @@ static bool EvaluateValue(PPValue &Resul PP.setCodeCompletionReached(); PP.LexNonComment(PeekTok); } - - // If this token's spelling is a pp-identifier, check to see if it is - // 'defined'
[PATCH] D26465: [Diag] Optimize DiagnosticIDs::getDiagnosticSeverity
ogoffart added a comment. ping? https://reviews.llvm.org/D26465 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D26350: Keep invalid Switch in the AST
ogoffart added a comment. ping? https://reviews.llvm.org/D26350 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11
ogoffart added a comment. Ping? I guess i coud just commit it now. https://reviews.llvm.org/D21502 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r285883 - Fix heuristics skipping invalid ctor-initializers with C++11
Author: ogoffart Date: Thu Nov 3 02:36:17 2016 New Revision: 285883 URL: http://llvm.org/viewvc/llvm-project?rev=285883&view=rev Log: Fix heuristics skipping invalid ctor-initializers with C++11 Use better heuristics to detect if a '{' might be the start of the constructor body or not. Especially when there is a completion token. Fix the test 'test/CodeCompletion/ctor-initializer.cpp ' when clang defaults to c++11 The problem was is how we recover invalid code in the ctor-init part as we skip the function body. In particular, we want to know if a '{' is the begining of the body. In C++03, we always consider it as the beginng of the body. The problem was that in C++11, it may be the start of an initializer, so we skip over it, causing further parse errors later. (It is important that we are able to parse correctly the rest of the class definition, to know what are the class member, for example) This commit is improving the heuristics to decide if the '{' is starting a function body. The rules are the following: If we are not in a template argument, and that the previous tokens are not an identifier, or a >, then it is much more likely to be the function body. We verify that further by checking the token after the matching '}' The commit also fix the behavior when there is a code_completion token in the ctor-initializers. Differential Revision: https://reviews.llvm.org/D21502 Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp cfe/trunk/test/CodeCompletion/ctor-initializer.cpp Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=285883&r1=285882&r2=285883&view=diff == --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original) +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Thu Nov 3 02:36:17 2016 @@ -832,22 +832,30 @@ bool Parser::ConsumeAndStoreFunctionProl } } - if (Tok.isOneOf(tok::identifier, tok::kw_template)) { + if (Tok.is(tok::identifier)) { Toks.push_back(Tok); ConsumeToken(); - } else if (Tok.is(tok::code_completion)) { -Toks.push_back(Tok); -ConsumeCodeCompletionToken(); -// Consume the rest of the initializers permissively. -// FIXME: We should be able to perform code-completion here even if -//there isn't a subsequent '{' token. -MightBeTemplateArgument = true; -break; } else { break; } } while (Tok.is(tok::coloncolon)); +if (Tok.is(tok::code_completion)) { + Toks.push_back(Tok); + ConsumeCodeCompletionToken(); + if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype)) { +// Could be the start of another member initializer (the ',' has not +// been written yet) +continue; + } +} + +if (Tok.is(tok::comma)) { + // The initialization is missing, we'll diagnose it later. + Toks.push_back(Tok); + ConsumeToken(); + continue; +} if (Tok.is(tok::less)) MightBeTemplateArgument = true; @@ -888,6 +896,26 @@ bool Parser::ConsumeAndStoreFunctionProl // means the initializer is malformed; we'll diagnose it later. if (!getLangOpts().CPlusPlus11) return false; + + const Token &PreviousToken = Toks[Toks.size() - 2]; + if (!MightBeTemplateArgument && + !PreviousToken.isOneOf(tok::identifier, tok::greater, + tok::greatergreater)) { +// If the opening brace is not preceded by one of these tokens, we are +// missing the mem-initializer-id. In order to recover better, we need +// to use heuristics to determine if this '{' is most likely the +// begining of a brace-init-list or the function body. +// Check the token after the corresponding '}'. +TentativeParsingAction PA(*this); +if (SkipUntil(tok::r_brace) && +!Tok.isOneOf(tok::comma, tok::ellipsis, tok::l_brace)) { + // Consider there was a malformed initializer and this is the start + // of the function body. We'll diagnose it later. + PA.Revert(); + return false; +} +PA.Revert(); + } } // Grab the initializer (or the subexpression of the template argument). Modified: cfe/trunk/test/CodeCompletion/ctor-initializer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/ctor-initializer.cpp?rev=285883&r1=285882&r2=285883&view=diff == --- cfe/trunk/test/CodeCompletion/ctor-initializer.cpp (original) +++ cfe/trunk/test/CodeCompletion/ctor-initializer.cpp Thu Nov 3 02:36:17 2016 @@ -1,11 +1,13 @@ struct Base1 { Base1() : {} - // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -ch
[PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11
This revision was automatically updated to reflect the committed changes. Closed by commit rL285883: Fix heuristics skipping invalid ctor-initializers with C++11 (authored by ogoffart). Changed prior to commit: https://reviews.llvm.org/D21502?vs=69223&id=76819#toc Repository: rL LLVM https://reviews.llvm.org/D21502 Files: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp cfe/trunk/test/CodeCompletion/ctor-initializer.cpp Index: cfe/trunk/test/CodeCompletion/ctor-initializer.cpp === --- cfe/trunk/test/CodeCompletion/ctor-initializer.cpp +++ cfe/trunk/test/CodeCompletion/ctor-initializer.cpp @@ -1,11 +1,13 @@ struct Base1 { Base1() : {} - // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>) // CHECK-CC1: COMPLETION: Pattern : member2(<#args#> Base1(int) : member1(123), {} - // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:7:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>) // CHECK-CC2: COMPLETION: Pattern : member2(<#args#> @@ -21,21 +23,40 @@ }; Derived::Derived() : {} -// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>) // CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>) Derived::Derived(int) try : { } catch (...) { } -// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:28:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s // CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>) // CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>) Derived::Derived(float) try : Base1(), { } catch (...) { } -// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:35:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s // CHECK-CC5-NOT: COMPLETION: Pattern : Base1(<#args#>) // CHECK-CC5: COMPLETION: Pattern : deriv1(<#args#>) + +struct A { + A() : , member2() {} + // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s + // CHECK-CC6: COMPLETION: Pattern : member1(<#args#> + int member1, member2; +}; + +struct B { + B() : member2() {} + // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s + // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s + // CHECK-CC7: COMPLETION: Pattern : member1(<#args#> + int member1, member2; +}; Index: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp === --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp @@ -832,22 +832,30 @@ } } - if (Tok.isOneOf(tok::identifier, tok::kw_template)) { + if (Tok.is(tok::identifier)) { Toks.push_back(Tok); ConsumeToken(); - } else if (Tok.is(tok::code_completion)) { -Toks.push_back(Tok); -ConsumeCodeCompletionToken(); -// Consume the rest of the initializers permissively. -// FIXME: We should be able to perform code-completion here even if -//there isn't a subsequent '{' token. -MightBeTemplateArgument = true; -break; } else { break; } } while (Tok.is(tok::coloncolon)); +if (Tok.is(tok::code_completion)) { + Toks.push_back(Tok); + ConsumeCodeCompletionToken(); + if (Tok.isOneOf(tok::identifier,
[PATCH] D26285: [index] Expose FriendDecl
ogoffart added a comment. KDevelop bug report: https://bugs.kde.org/show_bug.cgi?id=360509 https://reviews.llvm.org/D26285 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D26285: [index] Expose FriendDecl
ogoffart created this revision. ogoffart added reviewers: cfe-commits, alexey.klimov.dev, bkramer. I need to be able to visit friend declarations (the function) for the clang based qdoc (documentation parser). This also fix KDevelop not highlighting friend declarations. (Espetialy ennoying when declaring an operator with a body) https://reviews.llvm.org/D26285 Files: include/clang-c/Index.h lib/Sema/SemaCodeComplete.cpp test/Index/load-classes.cpp tools/libclang/CIndex.cpp tools/libclang/CursorVisitor.h Index: tools/libclang/CursorVisitor.h === --- tools/libclang/CursorVisitor.h +++ tools/libclang/CursorVisitor.h @@ -239,7 +239,8 @@ bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); bool VisitStaticAssertDecl(StaticAssertDecl *D); - + bool VisitFriendDecl(FriendDecl *D); + // Name visitor bool VisitDeclarationNameInfo(DeclarationNameInfo Name); bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range); Index: tools/libclang/CIndex.cpp === --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -1249,6 +1249,17 @@ return false; } +bool CursorVisitor::VisitFriendDecl(FriendDecl *D) { + if (NamedDecl *FriendD = D->getFriendDecl()) { +if (Visit(MakeCXCursor(FriendD, TU, RegionOfInterest))) + return true; + } else if (TypeSourceInfo *TI = D->getFriendType()) { +if (Visit(TI->getTypeLoc())) + return true; + } + return false; +} + bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) { switch (Name.getName().getNameKind()) { case clang::DeclarationName::Identifier: @@ -4923,6 +4934,8 @@ return cxstring::createRef("TypeAliasTemplateDecl"); case CXCursor_StaticAssert: return cxstring::createRef("StaticAssert"); + case CXCursor_FriendDecl: +return cxstring::createRef("FriendDecl"); } llvm_unreachable("Unhandled CXCursorKind"); Index: test/Index/load-classes.cpp === --- test/Index/load-classes.cpp +++ test/Index/load-classes.cpp @@ -18,13 +18,18 @@ virtual void virtualMemberFunction(); virtual void pureVirtualMemberFunction() = 0; + + friend void friendFunction(); + template + friend void friendFunctionTemplate(); + friend class F; }; X::X(int value) { } // RUN: c-index-test -test-load-source all %s | FileCheck %s -// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 21:2] +// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 26:2] // CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 (converting constructor) Extent=[4:3 - 4:15] [access=public] // FIXME: missing TypeRef in the constructor name // CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14] @@ -46,7 +51,14 @@ // CHECK: load-classes.cpp:16:21: TemplateTypeParameter=T:16:21 (Definition) Extent=[16:12 - 16:22] [access=public] // CHECK: load-classes.cpp:19:16: CXXMethod=virtualMemberFunction:19:16 (virtual) Extent=[19:3 - 19:39] [access=private] // CHECK: load-classes.cpp:20:16: CXXMethod=pureVirtualMemberFunction:20:16 (virtual) (pure) Extent=[20:3 - 20:47] [access=private] -// CHECK: load-classes.cpp:23:4: CXXConstructor=X:23:4 (Definition) (converting constructor) Extent=[23:1 - 24:2] [access=public] -// CHECK: load-classes.cpp:23:1: TypeRef=struct X:3:8 Extent=[23:1 - 23:2] -// CHECK: load-classes.cpp:23:10: ParmDecl=value:23:10 (Definition) Extent=[23:6 - 23:15] -// CHECK: load-classes.cpp:23:17: CompoundStmt= Extent=[23:17 - 24:2] +// CHECK: load-classes.cpp:22:15: FriendDecl=:22:15 Extent=[22:3 - 22:31] [access=public] +// CHECK: load-classes.cpp:22:15: FunctionDecl=friendFunction:22:15 Extent=[22:3 - 22:31] [access=public] +// CHECK: load-classes.cpp:24:15: FriendDecl=:24:15 Extent=[23:3 - 24:39] [access=public] +// CHECK: load-classes.cpp:24:15: FunctionTemplate=friendFunctionTemplate:24:15 Extent=[23:3 - 24:39] [access=public] +// CHECK: load-classes.cpp:23:22: TemplateTypeParameter=T:23:22 (Definition) Extent=[23:13 - 23:23] [access=public] +// CHECK: load-classes.cpp:25:10: FriendDecl=:25:10 Extent=[25:3 - 25:17] [access=public] +// CHECK: load-classes.cpp:25:16: TypeRef=class F:25:16 Extent=[25:16 - 25:17] +// CHECK: load-classes.cpp:28:4: CXXConstructor=X:28:4 (Definition) (converting constructor) Extent=[28:1 - 29:2] [access=public] +// CHECK: load-classes.cpp:28:1: TypeRef=struct X:3:8 Extent=[28:1 - 28:2] +// CHECK: load-classes.cpp:28:10: ParmDecl=value:28:10 (Definition) Extent=[28:6 - 28:15] +// CHECK: load-classes.cpp:28:17: CompoundStmt= Extent=[28:17 - 29:2] Index: lib/Sema/SemaCodeComplete.cpp === --- lib/Sema/SemaCodeComplete.cpp +++ lib/Sema/SemaCodeComplete.cpp
r285984 - [index] Expose FriendDecl
Author: ogoffart Date: Fri Nov 4 01:29:27 2016 New Revision: 285984 URL: http://llvm.org/viewvc/llvm-project?rev=285984&view=rev Log: [index] Expose FriendDecl Differential Revision: https://reviews.llvm.org/D26285 Modified: cfe/trunk/include/clang-c/Index.h cfe/trunk/lib/Sema/SemaCodeComplete.cpp cfe/trunk/test/Index/load-classes.cpp cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/tools/libclang/CursorVisitor.h Modified: cfe/trunk/include/clang-c/Index.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=285984&r1=285983&r2=285984&view=diff == --- cfe/trunk/include/clang-c/Index.h (original) +++ cfe/trunk/include/clang-c/Index.h Fri Nov 4 01:29:27 2016 @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 35 +#define CINDEX_VERSION_MINOR 36 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 1) \ @@ -2404,8 +2404,12 @@ enum CXCursorKind { * \brief A static_assert or _Static_assert node */ CXCursor_StaticAssert = 602, + /** + * \brief a friend declaration. + */ + CXCursor_FriendDecl= 603, CXCursor_FirstExtraDecl= CXCursor_ModuleImportDecl, - CXCursor_LastExtraDecl = CXCursor_StaticAssert, + CXCursor_LastExtraDecl = CXCursor_FriendDecl, /** * \brief A code completion overload candidate. Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=285984&r1=285983&r2=285984&view=diff == --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original) +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Nov 4 01:29:27 2016 @@ -3100,6 +3100,7 @@ CXCursorKind clang::getCursorKindForDecl return CXCursor_ClassTemplatePartialSpecialization; case Decl::UsingDirective: return CXCursor_UsingDirective; case Decl::StaticAssert: return CXCursor_StaticAssert; +case Decl::Friend: return CXCursor_FriendDecl; case Decl::TranslationUnit:return CXCursor_TranslationUnit; case Decl::Using: Modified: cfe/trunk/test/Index/load-classes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/load-classes.cpp?rev=285984&r1=285983&r2=285984&view=diff == --- cfe/trunk/test/Index/load-classes.cpp (original) +++ cfe/trunk/test/Index/load-classes.cpp Fri Nov 4 01:29:27 2016 @@ -18,13 +18,18 @@ private: virtual void virtualMemberFunction(); virtual void pureVirtualMemberFunction() = 0; + + friend void friendFunction(); + template + friend void friendFunctionTemplate(); + friend class F; }; X::X(int value) { } // RUN: c-index-test -test-load-source all %s | FileCheck %s -// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 21:2] +// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 26:2] // CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 (converting constructor) Extent=[4:3 - 4:15] [access=public] // FIXME: missing TypeRef in the constructor name // CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14] @@ -46,7 +51,14 @@ X::X(int value) { // CHECK: load-classes.cpp:16:21: TemplateTypeParameter=T:16:21 (Definition) Extent=[16:12 - 16:22] [access=public] // CHECK: load-classes.cpp:19:16: CXXMethod=virtualMemberFunction:19:16 (virtual) Extent=[19:3 - 19:39] [access=private] // CHECK: load-classes.cpp:20:16: CXXMethod=pureVirtualMemberFunction:20:16 (virtual) (pure) Extent=[20:3 - 20:47] [access=private] -// CHECK: load-classes.cpp:23:4: CXXConstructor=X:23:4 (Definition) (converting constructor) Extent=[23:1 - 24:2] [access=public] -// CHECK: load-classes.cpp:23:1: TypeRef=struct X:3:8 Extent=[23:1 - 23:2] -// CHECK: load-classes.cpp:23:10: ParmDecl=value:23:10 (Definition) Extent=[23:6 - 23:15] -// CHECK: load-classes.cpp:23:17: CompoundStmt= Extent=[23:17 - 24:2] +// CHECK: load-classes.cpp:22:15: FriendDecl=:22:15 Extent=[22:3 - 22:31] [access=public] +// CHECK: load-classes.cpp:22:15: FunctionDecl=friendFunction:22:15 Extent=[22:3 - 22:31] [access=public] +// CHECK: load-classes.cpp:24:15: FriendDecl=:24:15 Extent=[23:3 - 24:39] [access=public] +// CHECK: load-classes.cpp:24:15: FunctionTemplate=friendFunctionTemplate:24:15 Extent=[23:3 - 24:39] [access=public] +// CHECK: load-classes.cpp:23:22: TemplateTypeParameter=T:23:22 (Definition) Extent=[23:13 - 23:23] [access=public] +// CHECK: load-classes.cpp:25:10: FriendDecl=:25:10 Extent=[25:3 - 25:17] [access=public] +// CHECK: load-classes.cpp:25:16: TypeRef=class F:25:16 Extent=[25:16 - 25:17] +// CHECK
[PATCH] D26285: [index] Expose FriendDecl
This revision was automatically updated to reflect the committed changes. Closed by commit rL285984: [index] Expose FriendDecl (authored by ogoffart). Changed prior to commit: https://reviews.llvm.org/D26285?vs=76873&id=76913#toc Repository: rL LLVM https://reviews.llvm.org/D26285 Files: cfe/trunk/include/clang-c/Index.h cfe/trunk/lib/Sema/SemaCodeComplete.cpp cfe/trunk/test/Index/load-classes.cpp cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/tools/libclang/CursorVisitor.h Index: cfe/trunk/lib/Sema/SemaCodeComplete.cpp === --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp @@ -3100,6 +3100,7 @@ return CXCursor_ClassTemplatePartialSpecialization; case Decl::UsingDirective: return CXCursor_UsingDirective; case Decl::StaticAssert: return CXCursor_StaticAssert; +case Decl::Friend: return CXCursor_FriendDecl; case Decl::TranslationUnit:return CXCursor_TranslationUnit; case Decl::Using: Index: cfe/trunk/tools/libclang/CursorVisitor.h === --- cfe/trunk/tools/libclang/CursorVisitor.h +++ cfe/trunk/tools/libclang/CursorVisitor.h @@ -239,7 +239,8 @@ bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); bool VisitStaticAssertDecl(StaticAssertDecl *D); - + bool VisitFriendDecl(FriendDecl *D); + // Name visitor bool VisitDeclarationNameInfo(DeclarationNameInfo Name); bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range); Index: cfe/trunk/tools/libclang/CIndex.cpp === --- cfe/trunk/tools/libclang/CIndex.cpp +++ cfe/trunk/tools/libclang/CIndex.cpp @@ -1249,6 +1249,17 @@ return false; } +bool CursorVisitor::VisitFriendDecl(FriendDecl *D) { + if (NamedDecl *FriendD = D->getFriendDecl()) { +if (Visit(MakeCXCursor(FriendD, TU, RegionOfInterest))) + return true; + } else if (TypeSourceInfo *TI = D->getFriendType()) { +if (Visit(TI->getTypeLoc())) + return true; + } + return false; +} + bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) { switch (Name.getName().getNameKind()) { case clang::DeclarationName::Identifier: @@ -4923,6 +4934,8 @@ return cxstring::createRef("TypeAliasTemplateDecl"); case CXCursor_StaticAssert: return cxstring::createRef("StaticAssert"); + case CXCursor_FriendDecl: +return cxstring::createRef("FriendDecl"); } llvm_unreachable("Unhandled CXCursorKind"); Index: cfe/trunk/include/clang-c/Index.h === --- cfe/trunk/include/clang-c/Index.h +++ cfe/trunk/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 35 +#define CINDEX_VERSION_MINOR 36 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 1) \ @@ -2404,8 +2404,12 @@ * \brief A static_assert or _Static_assert node */ CXCursor_StaticAssert = 602, + /** + * \brief a friend declaration. + */ + CXCursor_FriendDecl= 603, CXCursor_FirstExtraDecl= CXCursor_ModuleImportDecl, - CXCursor_LastExtraDecl = CXCursor_StaticAssert, + CXCursor_LastExtraDecl = CXCursor_FriendDecl, /** * \brief A code completion overload candidate. Index: cfe/trunk/test/Index/load-classes.cpp === --- cfe/trunk/test/Index/load-classes.cpp +++ cfe/trunk/test/Index/load-classes.cpp @@ -18,13 +18,18 @@ virtual void virtualMemberFunction(); virtual void pureVirtualMemberFunction() = 0; + + friend void friendFunction(); + template + friend void friendFunctionTemplate(); + friend class F; }; X::X(int value) { } // RUN: c-index-test -test-load-source all %s | FileCheck %s -// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 21:2] +// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 26:2] // CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 (converting constructor) Extent=[4:3 - 4:15] [access=public] // FIXME: missing TypeRef in the constructor name // CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14] @@ -46,7 +51,14 @@ // CHECK: load-classes.cpp:16:21: TemplateTypeParameter=T:16:21 (Definition) Extent=[16:12 - 16:22] [access=public] // CHECK: load-classes.cpp:19:16: CXXMethod=virtualMemberFunction:19:16 (virtual) Extent=[19:3 - 19:39] [access=private] // CHECK: load-classes.cpp:20:16: CXXMethod=pureVirtualMemberFunction:20:16 (virtual) (pure) Extent=[20:3 - 20:47] [access=priv
r285986 - [python bindings] Expose CXCursor_FriendDecl as CursorKind.FRIEND_DECL
Author: ogoffart Date: Fri Nov 4 01:50:59 2016 New Revision: 285986 URL: http://llvm.org/viewvc/llvm-project?rev=285986&view=rev Log: [python bindings] Expose CXCursor_FriendDecl as CursorKind.FRIEND_DECL CXCursor_FriendDecl was added in r285984 Modified: cfe/trunk/bindings/python/clang/cindex.py Modified: cfe/trunk/bindings/python/clang/cindex.py URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/clang/cindex.py?rev=285986&r1=285985&r2=285986&view=diff == --- cfe/trunk/bindings/python/clang/cindex.py (original) +++ cfe/trunk/bindings/python/clang/cindex.py Fri Nov 4 01:50:59 2016 @@ -1317,6 +1317,8 @@ CursorKind.MODULE_IMPORT_DECL = CursorKi CursorKind.TYPE_ALIAS_TEMPLATE_DECL = CursorKind(601) # A static_assert or _Static_assert node CursorKind.STATIC_ASSERT = CursorKind(602) +# A friend declaration +CursorKind.FRIEND_DECL = CursorKind(603) # A code completion overload candidate. CursorKind.OVERLOAD_CANDIDATE = CursorKind(700) ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r285994 - [test] Test that static_assert is properly visited in liblcang
Author: ogoffart Date: Fri Nov 4 07:04:16 2016 New Revision: 285994 URL: http://llvm.org/viewvc/llvm-project?rev=285994&view=rev Log: [test] Test that static_assert is properly visited in liblcang Added: cfe/trunk/test/Index/load-staticassert.cpp Added: cfe/trunk/test/Index/load-staticassert.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/load-staticassert.cpp?rev=285994&view=auto == --- cfe/trunk/test/Index/load-staticassert.cpp (added) +++ cfe/trunk/test/Index/load-staticassert.cpp Fri Nov 4 07:04:16 2016 @@ -0,0 +1,11 @@ + +static_assert(2 + 2 == 4, "Simple maths"); + +// RUN: c-index-test -test-load-source all -fno-delayed-template-parsing -std=c++11 %s | FileCheck %s +// CHECK: load-staticassert.cpp:2:1: StaticAssert=:2:1 (Definition) Extent=[2:1 - 2:42] +// CHECK: load-staticassert.cpp:2:15: BinaryOperator= Extent=[2:15 - 2:25] +// CHECK: load-staticassert.cpp:2:15: BinaryOperator= Extent=[2:15 - 2:20] +// CHECK: load-staticassert.cpp:2:15: IntegerLiteral= Extent=[2:15 - 2:16] +// CHECK: load-staticassert.cpp:2:19: IntegerLiteral= Extent=[2:19 - 2:20] +// CHECK: load-staticassert.cpp:2:24: IntegerLiteral= Extent=[2:24 - 2:25] +// CHECK: load-staticassert.cpp:2:27: StringLiteral="Simple maths" Extent=[2:27 - 2:41] ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D26350: Keep invalid Switch in the AST
ogoffart created this revision. ogoffart added reviewers: rsmith, cfe-commits. - When the condition is invalid, replace it by an OpaqueValueExpr - When parsing an invalid CaseStmt, don't drop the sub statement, just return it instead. - In Sema::ActOnStartOfSwitchStmt, always keep the SwitchStmt, even if it has duplicate case or defaults statement or that the condition cannot be converted to an integral type. https://reviews.llvm.org/D26350 Files: lib/Parse/ParseStmt.cpp lib/Sema/SemaStmt.cpp test/Misc/ast-dump-invalid-switch.cpp Index: test/Misc/ast-dump-invalid-switch.cpp === --- /dev/null +++ test/Misc/ast-dump-invalid-switch.cpp @@ -0,0 +1,105 @@ +// RUN: not %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s + +/* This test ensures that the AST is still complete, even for invalid code */ + +namespace TestInvalidSwithCondition { +int f(int x) { + switch (_invalid_) { + case 0: +return 1; + default: +return 2; + } +} +} + +// CHECK: NamespaceDecl {{.*}} TestInvalidSwithCondition +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-SwitchStmt +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-OpaqueValueExpr +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: |-CaseStmt +// CHECK-NEXT: | |-IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT: | |-<<>> +// CHECK-NEXT: | `-ReturnStmt +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +// CHECK-NEXT: `-DefaultStmt +// CHECK-NEXT: `-ReturnStmt +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 2 + +namespace TestSwitchConditionNotIntegral { +int g(int *x) { + switch (x) { + case 0: +return 1; + default: +return 2; + } +} +} + +// CHECK: NamespaceDecl {{.*}} TestSwitchConditionNotIntegral +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-SwitchStmt +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-ImplicitCastExpr +// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'x' 'int *' +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: |-CaseStmt +// CHECK-NEXT: | |-IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT: | |-<<>> +// CHECK-NEXT: | `-ReturnStmt +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +// CHECK-NEXT: `-DefaultStmt +// CHECK-NEXT: `-ReturnStmt +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 2 + +namespace TestSwitchInvalidCases { +int g(int x) { + switch (x) { + case _invalid_: +return 1; + case _invalid_: +return 2; + case x: +return 3; + default: +return 4; + default: +return 5; + } +} +} + +// CHECK: NamespaceDecl {{.*}} TestSwitchInvalidCases +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-SwitchStmt +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-ImplicitCastExpr +// CHECK-NEXT: | `-DeclRefExpr {{.*}}'x' 'int' +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: |-ReturnStmt +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +// CHECK-NEXT: |-ReturnStmt +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 2 +// CHECK-NEXT: |-CaseStmt +// CHECK-NEXT: | |-DeclRefExpr {{.*}} 'x' 'int' +// CHECK-NEXT: | |-<<>> +// CHECK-NEXT: | `-ReturnStmt +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 3 +// CHECK-NEXT: |-DefaultStmt +// CHECK-NEXT: | `-ReturnStmt +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +// CHECK-NEXT: `-DefaultStmt +// CHECK-NEXT: `-ReturnStmt +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 5 Index: lib/Sema/SemaStmt.cpp === --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -666,7 +666,12 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Stmt *InitStmt, ConditionResult Cond) { if (Cond.isInvalid()) -return StmtError(); +Cond = ConditionResult( +*this, nullptr, +MakeFullExpr(new (Context) OpaqueValueExpr(SourceLocation(), + Context.IntTy, VK_RValue), + SwitchLoc), +false); getCurFunction()->setHasBranchIntoScope(); @@ -768,7 +773,7 @@ // type, when we started the switch statement. If we don't have an // appropriate type now, just return an error. if (!CondType->isIntegralOrEnumerationType()) - return StmtError(); + return SS; if (CondExpr->isKnownToHaveBooleanValue()) { // switch(bool_expr) {..
[PATCH] D26350: Keep invalid Switch in the AST
ogoffart added a comment. I believe only the change in ActOnFinishSwitchStmt might be controversial. Is it breaking an invariant than having switches kept in the AST? https://reviews.llvm.org/D26350 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D26465: [Diag] Optimize DiagnosticIDs::getDiagnosticSeverity
ogoffart created this revision. ogoffart added reviewers: cfe-commits, rsmith. Herald added a subscriber: sanjoy. DiagnosticIDs::getDiagnosticSeverity function turns out to take a lot of time in getDecomposedLoc. It is called quite often from different places. (For example from Sema::CheckTemplateArgument which attempt to emit warn_cxx98_compat_* diagnostics.) In most cases, the diagnostics are not overridden by pragmas and the mapping from the command line is good enough. This commit adds a bit in the the first mapping which specify if we should look up the real mapping. This saves more than 5% of the parsing time according to perf. https://reviews.llvm.org/D26465 Files: include/clang/Basic/Diagnostic.h include/clang/Basic/DiagnosticIDs.h lib/Basic/Diagnostic.cpp lib/Basic/DiagnosticIDs.cpp lib/Serialization/ASTReader.cpp Index: lib/Serialization/ASTReader.cpp === --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -5299,6 +5299,10 @@ diag::Severity Map = (diag::Severity)F.PragmaDiagMappings[Idx++]; DiagnosticMapping Mapping = Diag.makeUserMapping(Map, Loc); Diag.GetCurDiagState()->setMapping(DiagID, Mapping); + +// We are overriding a default behavior +Diag.DiagStates.front().getOrAddMapping(DiagID).setMightBeOverriden( +true); } } } Index: lib/Basic/DiagnosticIDs.cpp === --- lib/Basic/DiagnosticIDs.cpp +++ lib/Basic/DiagnosticIDs.cpp @@ -406,25 +406,29 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, const DiagnosticsEngine &Diag) const { assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE); - // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. diag::Severity Result = diag::Severity::Fatal; - DiagnosticsEngine::DiagStatePointsTy::iterator -Pos = Diag.GetDiagStatePointForLoc(Loc); - DiagnosticsEngine::DiagState *State = Pos->State; - - // Get the mapping information, or compute it lazily. - DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID); + // Calling GetDiagStatePointForLoc might be costly as it needs to create + // FullSourceLoc and compare them to the ones in the states. So first query + // the base state and check if it might be overridden. + DiagnosticsEngine::DiagState &BaseState = Diag.DiagStates.front(); + assert(&BaseState == Diag.DiagStatePoints.front().State); + DiagnosticMapping *Mapping = &BaseState.getOrAddMapping((diag::kind)DiagID); + if (Mapping->mightBeOverriden()) { +DiagnosticsEngine::DiagStatePointsTy::iterator Pos = +Diag.GetDiagStatePointForLoc(Loc); +Mapping = &Pos->State->getOrAddMapping((diag::kind)DiagID); + } // TODO: Can a null severity really get here? - if (Mapping.getSeverity() != diag::Severity()) -Result = Mapping.getSeverity(); + if (Mapping->getSeverity() != diag::Severity()) +Result = Mapping->getSeverity(); // Upgrade ignored diagnostics if -Weverything is enabled. if (Diag.EnableAllWarnings && Result == diag::Severity::Ignored && - !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK) + !Mapping->isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK) Result = diag::Severity::Warning; // Ignore -pedantic diagnostics inside __extension__ blocks. @@ -437,7 +441,7 @@ // For extension diagnostics that haven't been explicitly mapped, check if we // should upgrade the diagnostic. - if (IsExtensionDiag && !Mapping.isUser()) + if (IsExtensionDiag && !Mapping->isUser()) Result = std::max(Result, Diag.ExtBehavior); // At this point, ignored errors can no longer be upgraded. @@ -451,14 +455,14 @@ // If -Werror is enabled, map warnings to errors unless explicitly disabled. if (Result == diag::Severity::Warning) { -if (Diag.WarningsAsErrors && !Mapping.hasNoWarningAsError()) +if (Diag.WarningsAsErrors && !Mapping->hasNoWarningAsError()) Result = diag::Severity::Error; } // If -Wfatal-errors is enabled, map errors to fatal unless explicity // disabled. if (Result == diag::Severity::Error) { -if (Diag.ErrorsAsFatal && !Mapping.hasNoErrorAsFatal()) +if (Diag.ErrorsAsFatal && !Mapping->hasNoErrorAsFatal()) Result = diag::Severity::Fatal; } Index: lib/Basic/Diagnostic.cpp === --- lib/Basic/Diagnostic.cpp +++ lib/Basic/Diagnostic.cpp @@ -201,6 +201,11 @@ } DiagnosticMapping Mapping = makeUserMapping(Map, L); + if (Loc.isValid()) { +// We are potentially overriding a default behavior +DiagStates.front().getOrAddMapping(Diag).setMightBeOverriden(true); + } + // Common case; setting all the diagnostics of a group in one place.
[PATCH] Keep the IfStmt node even if the condition is invalid
Hi, Please review the attached patch. It does not discard the full 'if' statement if the condition is invalid. This is quite useful for IDE's or other tools which would like to recover as much as possible even if there are a few errors in the code, and discarding the full 'if' bodies is unfortunate. Thanks. -- Olivier P.S: For the same reason, i'm also trying to fix the fact that if there is any typo in an expression statement, the full statement is discarded. The reason is i believe that Sema::CorrectDelayedTyposInExpr just return null if any typo could not be corrected. That's unrelated to this patch, but i still would welcome hint on how to fix it. Should CorrectDelayedTyposInExpr somehow replace the TypoExpr instead of removing them? Or should it create a new node (some kind of error ErrorExpr)? Or should the caller of CorrectDelayedTyposInExpr be changed to keep the original? >From 8f5f74755cfa0c6165caff65dcc07b0d2543f481 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Sat, 12 Sep 2015 16:09:34 +0200 Subject: [PATCH] Keep the IfStmt node even if the condition is invalid This is important to keep the information in IDE or other tools even if the code contains a few errors --- lib/Sema/SemaStmt.cpp | 22 +++--- test/Misc/ast-dump-invalid.cpp | 23 +++ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index c39c80d..97a1160 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -483,13 +483,6 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { - // If the condition was invalid, discard the if statement. We could recover - // better by replacing it with a valid expr, but don't do that yet. - if (!CondVal.get() && !CondVar) { -getCurFunction()->setHasDroppedStmt(); -return StmtError(); - } - ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = nullptr; @@ -501,18 +494,17 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, return StmtError(); } Expr *ConditionExpr = CondResult.getAs(); - if (!ConditionExpr) -return StmtError(); + if (ConditionExpr) { +DiagnoseUnusedExprResult(thenStmt); - DiagnoseUnusedExprResult(thenStmt); +if (!elseStmt) { + DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, +diag::warn_empty_if_body); +} - if (!elseStmt) { -DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, - diag::warn_empty_if_body); +DiagnoseUnusedExprResult(elseStmt); } - DiagnoseUnusedExprResult(elseStmt); - return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, thenStmt, ElseLoc, elseStmt); } diff --git a/test/Misc/ast-dump-invalid.cpp b/test/Misc/ast-dump-invalid.cpp index 3b97cc6..899bfa0 100644 --- a/test/Misc/ast-dump-invalid.cpp +++ b/test/Misc/ast-dump-invalid.cpp @@ -18,3 +18,26 @@ void f(T i, T j) { // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'T' // CHECK-NEXT: |-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'i' 'T' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'j' 'T' + + +namespace TestInvalidIf { +int g(int i) { + if (invalid_condition) +return 4; + else +return i; +} +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-IfStmt {{.*}} +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-ReturnStmt {{.*}} +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + -- 2.6.0 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D13344: Keep the IfStmt node even if the condition is invalid
ogoffart created this revision. ogoffart added a reviewer: cfe-commits. This is quite useful for IDE's or other tools which would like to recover as much as possible even if there are a few errors in the code, and discarding the full 'if' bodies is unfortunate. http://reviews.llvm.org/D13344 Files: lib/Sema/SemaStmt.cpp test/Misc/ast-dump-invalid.cpp Index: test/Misc/ast-dump-invalid.cpp === --- test/Misc/ast-dump-invalid.cpp +++ test/Misc/ast-dump-invalid.cpp @@ -18,3 +18,26 @@ // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'T' // CHECK-NEXT: |-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'i' 'T' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'j' 'T' + + +namespace TestInvalidIf { +int g(int i) { + if (invalid_condition) +return 4; + else +return i; +} +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-IfStmt {{.*}} +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-ReturnStmt {{.*}} +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + Index: lib/Sema/SemaStmt.cpp === --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -483,13 +483,6 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { - // If the condition was invalid, discard the if statement. We could recover - // better by replacing it with a valid expr, but don't do that yet. - if (!CondVal.get() && !CondVar) { -getCurFunction()->setHasDroppedStmt(); -return StmtError(); - } - ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = nullptr; @@ -501,18 +494,17 @@ return StmtError(); } Expr *ConditionExpr = CondResult.getAs(); - if (!ConditionExpr) -return StmtError(); + if (ConditionExpr) { +DiagnoseUnusedExprResult(thenStmt); - DiagnoseUnusedExprResult(thenStmt); +if (!elseStmt) { + DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, +diag::warn_empty_if_body); +} - if (!elseStmt) { -DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, - diag::warn_empty_if_body); +DiagnoseUnusedExprResult(elseStmt); } - DiagnoseUnusedExprResult(elseStmt); - return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, thenStmt, ElseLoc, elseStmt); } Index: test/Misc/ast-dump-invalid.cpp === --- test/Misc/ast-dump-invalid.cpp +++ test/Misc/ast-dump-invalid.cpp @@ -18,3 +18,26 @@ // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'T' // CHECK-NEXT: |-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'i' 'T' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'j' 'T' + + +namespace TestInvalidIf { +int g(int i) { + if (invalid_condition) +return 4; + else +return i; +} +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-IfStmt {{.*}} +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-ReturnStmt {{.*}} +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + Index: lib/Sema/SemaStmt.cpp === --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -483,13 +483,6 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { - // If the condition was invalid, discard the if statement. We could recover - // better by replacing it with a valid expr, but don't do that yet. - if (!CondVal.get() && !CondVar) { -getCurFunction()->setHasDroppedStmt(); -return StmtError(); - } - ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = nullptr; @@ -501,18 +494,17 @@ return StmtError(); } Expr *ConditionExpr = CondResult.getAs(); - if (!ConditionExpr) -return StmtError(); + if (ConditionExpr) { +DiagnoseUnusedExprResult(thenStmt); - DiagnoseUnusedExprResult(thenStmt); +if (!elseStmt) { + DiagnoseEmptyStmtBody(Condi
[PATCH] Fix crash with two typos in the arguments of a function
Hi, Attached you will find the fix for a crash on invalid code in clang 3.7 It crashes on this code: void fn2() { f(THIS_IS_AN_ERROR, afunction(afunction_)); } The problem is that the arguments are of TheCall are reset later to the ones in Args. Some TypoExpr that have already been diagnosed will assert later in Sema::getTypoExprState. I was wondering if instead of reusing the TheCall->getArgs() array I should copy the arguments in an array on the stack instead. I suppose I should commit to trunk and ask someone to merge into release_37? Regards -- Olivier >From 7da528047bb8d925078cdc8226a9961f74130b93 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 14 Aug 2015 12:59:17 +0200 Subject: [PATCH] Fix crash with two typos in the arguments of a function The problem is that the arguments are of TheCall are reset later to the ones in Args, making TypoExpr put back. Some TypoExpr that have already been diagnosed and will assert later in Sema::getTypoExprState --- lib/Sema/SemaExpr.cpp | 1 + test/Sema/typo-correction.c | 6 ++ 2 files changed, 7 insertions(+) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index dd99ad2..a271cbd 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4937,6 +4937,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (!Result.isUsable()) return ExprError(); TheCall = dyn_cast(Result.get()); if (!TheCall) return Result; +Args = ArrayRef(TheCall->getArgs(), TheCall->getNumArgs()); } // Bail out early if calling a builtin with custom typechecking. diff --git a/test/Sema/typo-correction.c b/test/Sema/typo-correction.c index ff43064..4ef5057 100644 --- a/test/Sema/typo-correction.c +++ b/test/Sema/typo-correction.c @@ -49,3 +49,9 @@ extern double cabs(_Complex double z); void fn1() { cabs(errij); // expected-error {{use of undeclared identifier 'errij'}} } + +extern long afunction(int); // expected-note {{'afunction' declared here}} +void fn2() { + f(THIS_IS_AN_ERROR, // expected-error {{use of undeclared identifier 'THIS_IS_AN_ERROR'}} +afunction(afunction_)); // expected-error {{use of undeclared identifier 'afunction_'; did you mean 'afunction'?}} +} -- 2.5.0 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r245560 - Fix crash with two typos in the arguments of a function
Author: ogoffart Date: Thu Aug 20 08:11:14 2015 New Revision: 245560 URL: http://llvm.org/viewvc/llvm-project?rev=245560&view=rev Log: Fix crash with two typos in the arguments of a function The problem is that the arguments are of TheCall are reset later to the ones in Args, making TypoExpr put back. Some TypoExpr that have already been diagnosed and will assert later in Sema::getTypoExprState Modified: cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/Sema/typo-correction.c Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=245560&r1=245559&r2=245560&view=diff == --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Aug 20 08:11:14 2015 @@ -4937,6 +4937,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, Na if (!Result.isUsable()) return ExprError(); TheCall = dyn_cast(Result.get()); if (!TheCall) return Result; +Args = ArrayRef(TheCall->getArgs(), TheCall->getNumArgs()); } // Bail out early if calling a builtin with custom typechecking. Modified: cfe/trunk/test/Sema/typo-correction.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/typo-correction.c?rev=245560&r1=245559&r2=245560&view=diff == --- cfe/trunk/test/Sema/typo-correction.c (original) +++ cfe/trunk/test/Sema/typo-correction.c Thu Aug 20 08:11:14 2015 @@ -49,3 +49,9 @@ extern double cabs(_Complex double z); void fn1() { cabs(errij); // expected-error {{use of undeclared identifier 'errij'}} } + +extern long afunction(int); // expected-note {{'afunction' declared here}} +void fn2() { + f(THIS_IS_AN_ERROR, // expected-error {{use of undeclared identifier 'THIS_IS_AN_ERROR'}} +afunction(afunction_)); // expected-error {{use of undeclared identifier 'afunction_'; did you mean 'afunction'?}} +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] fix parentheses location in a CXXConstructExpr
Hi, Please review the attached patch. In Sema::BuildCXXFunctionalCastExpr, if the class has a destructor, the Op.SrcExpr might be a CXXBindTemporaryExpr which we need to unwrap. In the testcase, the first new CHECK worked (because A does not have a destructor), but the second CHECK failed (did not include the last parenthese) because D has a destructor. I used dyn_cast_or_null just to be safe, becasue i don't know if it is possible for the BindExpr->getSubExpr() to be null. Thanks -- Olivier >From 919a61662f483404b37859f795048bc864c0c7ac Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 28 Aug 2015 17:32:55 +0200 Subject: [PATCH] Fix the perentheses location when the constructor is called on a class that has a destructor --- lib/Sema/SemaCast.cpp | 7 +-- test/SemaCXX/sourceranges.cpp | 15 ++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index dea9c22..db276c6 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -2483,8 +2483,11 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false); if (Op.SrcExpr.isInvalid()) return ExprError(); - - if (CXXConstructExpr *ConstructExpr = dyn_cast(Op.SrcExpr.get())) + + auto ConstructExpr = dyn_cast(Op.SrcExpr.get()); + if (auto BindExpr = dyn_cast(Op.SrcExpr.get())) +ConstructExpr = dyn_cast_or_null(BindExpr->getSubExpr()); + if (ConstructExpr) ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc)); return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, diff --git a/test/SemaCXX/sourceranges.cpp b/test/SemaCXX/sourceranges.cpp index 9ba003a..8f2cfe5 100644 --- a/test/SemaCXX/sourceranges.cpp +++ b/test/SemaCXX/sourceranges.cpp @@ -7,7 +7,7 @@ class P { }; namespace foo { -class A { public: A() {} }; +class A { public: A(int = 0) {} }; enum B {}; typedef int C; } @@ -37,3 +37,16 @@ void destruct(foo::A *a1, foo::A *a2, P *p1) { // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} '' ->~P p1->~P(); } + +struct D { + D(int); + ~D(); +}; + +void construct() { + using namespace foo; + A a = A(12); + // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} 'class foo::A' 'void (int)' + D d = D(12); + // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} 'struct D' 'void (int)' +} -- 2.5.0 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] fix parentheses location in a CXXConstructExpr
On Monday 31. August 2015 08:07:58 Manuel Klimek wrote: > On Sat, Aug 29, 2015 at 12:23 PM Olivier Goffart via cfe-commits < > > cfe-commits@lists.llvm.org> wrote: > > Hi, > > > > Please review the attached patch. > > > > In Sema::BuildCXXFunctionalCastExpr, if the class has a destructor, the > > Op.SrcExpr might be a CXXBindTemporaryExpr which we need to unwrap. > > > > In the testcase, the first new CHECK worked (because A does not have a > > destructor), but the second CHECK failed (did not include the last > > parenthese) because D has a destructor. > > > > I used dyn_cast_or_null just to be safe, becasue i don't know if it is > > possible for the BindExpr->getSubExpr() to be null. > > Do you know why the added test for A says 'class foo::A' instead of > 'foo::A' as the other tests do in that file? I don't know. It seems it has to do with the fully quallified name vs. normal name. For example, if you dumpt the AST of: namespace foo { class A {} *a1 = new foo::A , *a2 = new A; } You get: [...] | |-VarDecl 0x1c9a7a0 col:29 a1 'class A *' cinit | | `-CXXNewExpr 0x1ce2648 'foo::A *' | | `-CXXConstructExpr 0x1ce2618 'foo::A':'class foo::A' 'void (void) throw()' | `-VarDecl 0x1ce26d0 col:48 a2 'class A *' cinit | `-CXXNewExpr 0x1ce2768 'class foo::A *' | `-CXXConstructExpr 0x1ce2738 'class foo::A' 'void (void) throw()' As you can see, when the type of CXXNewExpr is fully quialified, the 'class' keyword is omited, but for a2, it prints the 'class' keyword. The printed type of CXXConstructExpr is even more wierd when it is fully qualified. I guess that's because of ElaboratedTypePolicyRAII in TypePrinter.cpp But this is irrelevant for this patch and the problem it's trying to solve. The reason I used 'using namespace foo' in the test was just so the line with A and D have the same size. I just copy pasted the thing without thinking about that. -- Olivier ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] fix parentheses location in a CXXConstructExpr
On Thursday 3. September 2015 13:41:12 Richard Smith wrote: > On Thu, Sep 3, 2015 at 8:58 AM, Manuel Klimek wrote: > > On Tue, Sep 1, 2015 at 12:31 AM Olivier Goffart wrote: > >> On Monday 31. August 2015 08:07:58 Manuel Klimek wrote: > >> > On Sat, Aug 29, 2015 at 12:23 PM Olivier Goffart via cfe-commits < > >> > > >> > cfe-commits@lists.llvm.org> wrote: > >> > > Hi, > >> > > > >> > > Please review the attached patch. > >> > > > >> > > In Sema::BuildCXXFunctionalCastExpr, if the class has a destructor, > >> > >> the > >> > >> > > Op.SrcExpr might be a CXXBindTemporaryExpr which we need to unwrap. > >> > > > >> > > In the testcase, the first new CHECK worked (because A does not have > >> > > a > >> > > destructor), but the second CHECK failed (did not include the last > >> > > parenthese) because D has a destructor. > >> > > > >> > > I used dyn_cast_or_null just to be safe, becasue i don't know if it > >> > > is > >> > > possible for the BindExpr->getSubExpr() to be null. > >> > > >> > Do you know why the added test for A says 'class foo::A' instead of > >> > 'foo::A' as the other tests do in that file? > >> > >> I don't know. It seems it has to do with the fully quallified name vs. > >> normal > >> name. > >> > >> For example, if you dumpt the AST of: > >> namespace foo { class A {} *a1 = new foo::A , *a2 = new A; } > >> > >> You get: > >> > >> [...] > >> > >> | |-VarDecl 0x1c9a7a0 col:29 a1 'class A *' cinit > >> | | > >> | | `-CXXNewExpr 0x1ce2648 'foo::A *' > >> | | > >> | | `-CXXConstructExpr 0x1ce2618 'foo::A':'class foo::A' 'void > >> > >> (void) throw()' > >> > >> | `-VarDecl 0x1ce26d0 col:48 a2 'class A *' cinit > >> | > >> | `-CXXNewExpr 0x1ce2768 'class foo::A *' > >> | > >> | `-CXXConstructExpr 0x1ce2738 'class foo::A' 'void (void) > >> > >> throw()' > >> > >> > >> As you can see, when the type of CXXNewExpr is fully quialified, the > >> 'class' > >> keyword is omited, but for a2, it prints the 'class' keyword. > >> The printed type of CXXConstructExpr is even more wierd when it is fully > >> qualified. > >> > >> > >> I guess that's because of ElaboratedTypePolicyRAII in TypePrinter.cpp > >> > >> But this is irrelevant for this patch and the problem it's trying to > >> solve. > >> The reason I used 'using namespace foo' in the test was just so the line > >> with > >> A and D have the same size. I just copy pasted the thing without > >> thinking > >> about that. > > > > Makes sense. In that case I think it looks good, adding Richard to > > cross-check for the final approval. > > + auto ConstructExpr = dyn_cast(Op.SrcExpr.get()); > + if (auto BindExpr = dyn_cast(Op.SrcExpr.get())) > +ConstructExpr = > dyn_cast_or_null(BindExpr->getSubExpr()); > + if (ConstructExpr) > > It's slightly better to write this as: > > auto *SubExpr = Op.SrcExpr.get(); > if (auto *BindExpr = dyn_cast(SubExpr)) > SubExpr = BindExpr->getSubExpr(); > if (auto *ConstructExpr = dyn_cast(SubExpr)) > > Otherwise, LGTM. Thanks. So no dyn_cast_or_null? CXXBindTemporaryExpr::getSubExpr never returns null here? > [The root cause of the problem here is suboptimal design of this AST node. > It doesn't make sense for both CXXFunctionalCastExpr and CXXConstructExpr > to hold the locations of the same set of parens (and we can see from > StmtPrinter that CXXFunctionalCastExpr currently "owns" the parens). But > fixing that is a larger task, so let's just get this immediate bug fixed > for now.] [This is however quite convnient for me to get the location of the parentheses of a CXXConstructorExpr. There are may cases where CXXConstructorExpr is not in a CXXFunctionalCastExpr] -- Olivier ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r246844 - Fix the perentheses location when the constructor is called on a class that has a destructor
Author: ogoffart Date: Fri Sep 4 05:17:10 2015 New Revision: 246844 URL: http://llvm.org/viewvc/llvm-project?rev=246844&view=rev Log: Fix the perentheses location when the constructor is called on a class that has a destructor Modified: cfe/trunk/lib/Sema/SemaCast.cpp cfe/trunk/test/SemaCXX/sourceranges.cpp Modified: cfe/trunk/lib/Sema/SemaCast.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=246844&r1=246843&r2=246844&view=diff == --- cfe/trunk/lib/Sema/SemaCast.cpp (original) +++ cfe/trunk/lib/Sema/SemaCast.cpp Fri Sep 4 05:17:10 2015 @@ -2483,8 +2483,11 @@ ExprResult Sema::BuildCXXFunctionalCastE Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false); if (Op.SrcExpr.isInvalid()) return ExprError(); - - if (CXXConstructExpr *ConstructExpr = dyn_cast(Op.SrcExpr.get())) + + auto *SubExpr = Op.SrcExpr.get(); + if (auto *BindExpr = dyn_cast(SubExpr)) +SubExpr = BindExpr->getSubExpr(); + if (auto *ConstructExpr = dyn_cast(SubExpr)) ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc)); return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, Modified: cfe/trunk/test/SemaCXX/sourceranges.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/sourceranges.cpp?rev=246844&r1=246843&r2=246844&view=diff == --- cfe/trunk/test/SemaCXX/sourceranges.cpp (original) +++ cfe/trunk/test/SemaCXX/sourceranges.cpp Fri Sep 4 05:17:10 2015 @@ -7,7 +7,7 @@ class P { }; namespace foo { -class A { public: A() {} }; +class A { public: A(int = 0) {} }; enum B {}; typedef int C; } @@ -37,3 +37,16 @@ void destruct(foo::A *a1, foo::A *a2, P< // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} '' ->~P p1->~P(); } + +struct D { + D(int); + ~D(); +}; + +void construct() { + using namespace foo; + A a = A(12); + // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} 'class foo::A' 'void (int)' + D d = D(12); + // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} 'struct D' 'void (int)' +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13344: Keep the IfStmt node even if the condition is invalid
ogoffart added a comment. Are the analysis run if there is an error? I think the consumer should expect null condition anyway. But i'll try to add an ErrorExpr anyway. http://reviews.llvm.org/D13344 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13344: Keep the IfStmt node even if the condition is invalid
ogoffart updated this revision to Diff 37035. ogoffart added a comment. The updated patch uses OpaqueValueExpr http://reviews.llvm.org/D13344 Files: lib/Sema/SemaStmt.cpp test/Misc/ast-dump-invalid.cpp Index: test/Misc/ast-dump-invalid.cpp === --- test/Misc/ast-dump-invalid.cpp +++ test/Misc/ast-dump-invalid.cpp @@ -18,3 +18,26 @@ // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'T' // CHECK-NEXT: |-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'i' 'T' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'j' 'T' + + +namespace TestInvalidIf { +int g(int i) { + if (invalid_condition) +return 4; + else +return i; +} +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-IfStmt {{.*}} +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <> 'void' +// CHECK-NEXT: |-ReturnStmt {{.*}} +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + Index: lib/Sema/SemaStmt.cpp === --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -483,13 +483,6 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { - // If the condition was invalid, discard the if statement. We could recover - // better by replacing it with a valid expr, but don't do that yet. - if (!CondVal.get() && !CondVar) { -getCurFunction()->setHasDroppedStmt(); -return StmtError(); - } - ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = nullptr; @@ -497,22 +490,22 @@ ConditionVar = cast(CondVar); CondResult = CheckConditionVariable(ConditionVar, IfLoc, true); CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc); -if (CondResult.isInvalid()) - return StmtError(); } Expr *ConditionExpr = CondResult.getAs(); - if (!ConditionExpr) -return StmtError(); + if (ConditionExpr) { +DiagnoseUnusedExprResult(thenStmt); - DiagnoseUnusedExprResult(thenStmt); +if (!elseStmt) { + DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, +diag::warn_empty_if_body); +} - if (!elseStmt) { -DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, - diag::warn_empty_if_body); +DiagnoseUnusedExprResult(elseStmt); + } else { +ConditionExpr = new (Context) OpaqueValueExpr(SourceLocation(), + Context.VoidTy, VK_RValue); } - DiagnoseUnusedExprResult(elseStmt); - return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, thenStmt, ElseLoc, elseStmt); } Index: test/Misc/ast-dump-invalid.cpp === --- test/Misc/ast-dump-invalid.cpp +++ test/Misc/ast-dump-invalid.cpp @@ -18,3 +18,26 @@ // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'T' // CHECK-NEXT: |-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'i' 'T' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'j' 'T' + + +namespace TestInvalidIf { +int g(int i) { + if (invalid_condition) +return 4; + else +return i; +} +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-IfStmt {{.*}} +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <> 'void' +// CHECK-NEXT: |-ReturnStmt {{.*}} +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + Index: lib/Sema/SemaStmt.cpp === --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -483,13 +483,6 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { - // If the condition was invalid, discard the if statement. We could recover - // better by replacing it with a valid expr, but don't do that yet. - if (!CondVal.get() && !CondVar) { -getCurFunction()->setHasDroppedStmt(); -return StmtError(); - } - ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = nullptr; @@ -497,22 +490,22 @@ ConditionVar = ca
r249982 - Keep the IfStmt node even if the condition is invalid
Author: ogoffart Date: Sun Oct 11 12:27:29 2015 New Revision: 249982 URL: http://llvm.org/viewvc/llvm-project?rev=249982&view=rev Log: Keep the IfStmt node even if the condition is invalid This is important to keep the information in IDE or other tools even if the code contains a few errors Modified: cfe/trunk/lib/Sema/SemaStmt.cpp cfe/trunk/test/Misc/ast-dump-invalid.cpp Modified: cfe/trunk/lib/Sema/SemaStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=249982&r1=249981&r2=249982&view=diff == --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmt.cpp Sun Oct 11 12:27:29 2015 @@ -483,13 +483,6 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { - // If the condition was invalid, discard the if statement. We could recover - // better by replacing it with a valid expr, but don't do that yet. - if (!CondVal.get() && !CondVar) { -getCurFunction()->setHasDroppedStmt(); -return StmtError(); - } - ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = nullptr; @@ -497,22 +490,23 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, ConditionVar = cast(CondVar); CondResult = CheckConditionVariable(ConditionVar, IfLoc, true); CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc); -if (CondResult.isInvalid()) - return StmtError(); } Expr *ConditionExpr = CondResult.getAs(); - if (!ConditionExpr) -return StmtError(); + if (ConditionExpr) { +DiagnoseUnusedExprResult(thenStmt); - DiagnoseUnusedExprResult(thenStmt); - - if (!elseStmt) { -DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, - diag::warn_empty_if_body); +if (!elseStmt) { + DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, +diag::warn_empty_if_body); +} + +DiagnoseUnusedExprResult(elseStmt); + } else { +// Create a dummy Expr for the condition for error recovery +ConditionExpr = new (Context) OpaqueValueExpr(SourceLocation(), + Context.BoolTy, VK_RValue); } - DiagnoseUnusedExprResult(elseStmt); - return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, thenStmt, ElseLoc, elseStmt); } Modified: cfe/trunk/test/Misc/ast-dump-invalid.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-invalid.cpp?rev=249982&r1=249981&r2=249982&view=diff == --- cfe/trunk/test/Misc/ast-dump-invalid.cpp (original) +++ cfe/trunk/test/Misc/ast-dump-invalid.cpp Sun Oct 11 12:27:29 2015 @@ -18,3 +18,26 @@ void f(T i, T j) { // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'T' // CHECK-NEXT: |-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'i' 'T' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'j' 'T' + + +namespace TestInvalidIf { +int g(int i) { + if (invalid_condition) +return 4; + else +return i; +} +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-IfStmt {{.*}} +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <> '_Bool' +// CHECK-NEXT: |-ReturnStmt {{.*}} +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13344: Keep the IfStmt node even if the condition is invalid
ogoffart abandoned this revision. ogoffart marked an inline comment as done. ogoffart added a comment. commited as r249982. (I forgot to add the link to reviews.llvm.org in the commit message. I'll do it next time) http://reviews.llvm.org/D13344 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D16973: Fix ICE with constexpr and friend functions
ogoffart created this revision. ogoffart added reviewers: rsmith, cfe-commits. Fix a crash while parsing this code: struct X { friend constexpr int foo(X*) { return 12; } static constexpr int j = foo(static_cast(nullptr)); }; I also added a test for the static function case because i don't think this was tested before. http://reviews.llvm.org/D16973 Files: lib/AST/ExprConstant.cpp test/SemaCXX/constant-expression-cxx11.cpp Index: test/SemaCXX/constant-expression-cxx11.cpp === --- test/SemaCXX/constant-expression-cxx11.cpp +++ test/SemaCXX/constant-expression-cxx11.cpp @@ -2005,3 +2005,13 @@ constexpr int a = *f().p; constexpr int b = *g().p; } + +namespace IncompleteClass { + struct XX { +static constexpr int f(XX*) { return 1; } // expected-note {{here}} +friend constexpr int g(XX*) { return 2; } // expected-note {{here}} + +static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}} expected-note {{undefined function 'f' cannot be used in a constant expression}} +static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}} expected-note {{undefined function 'g' cannot be used in a constant expression}} + }; +} \ No newline at end of file Index: lib/AST/ExprConstant.cpp === --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -3749,7 +3749,8 @@ return false; // Can we evaluate this function call? - if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) + if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl() + && Definition->getBody()) return true; if (Info.getLangOpts().CPlusPlus11) { Index: test/SemaCXX/constant-expression-cxx11.cpp === --- test/SemaCXX/constant-expression-cxx11.cpp +++ test/SemaCXX/constant-expression-cxx11.cpp @@ -2005,3 +2005,13 @@ constexpr int a = *f().p; constexpr int b = *g().p; } + +namespace IncompleteClass { + struct XX { +static constexpr int f(XX*) { return 1; } // expected-note {{here}} +friend constexpr int g(XX*) { return 2; } // expected-note {{here}} + +static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}} expected-note {{undefined function 'f' cannot be used in a constant expression}} +static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}} expected-note {{undefined function 'g' cannot be used in a constant expression}} + }; +} \ No newline at end of file Index: lib/AST/ExprConstant.cpp === --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -3749,7 +3749,8 @@ return false; // Can we evaluate this function call? - if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) + if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl() + && Definition->getBody()) return true; if (Info.getLangOpts().CPlusPlus11) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16973: Fix ICE with constexpr and friend functions
ogoffart updated this revision to Diff 47146. ogoffart added a comment. Optimized by avoiding repeated call to getBody http://reviews.llvm.org/D16973 Files: lib/AST/ExprConstant.cpp test/SemaCXX/constant-expression-cxx11.cpp Index: test/SemaCXX/constant-expression-cxx11.cpp === --- test/SemaCXX/constant-expression-cxx11.cpp +++ test/SemaCXX/constant-expression-cxx11.cpp @@ -2005,3 +2005,13 @@ constexpr int a = *f().p; constexpr int b = *g().p; } + +namespace IncompleteClass { + struct XX { +static constexpr int f(XX*) { return 1; } // expected-note {{here}} +friend constexpr int g(XX*) { return 2; } // expected-note {{here}} + +static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}} expected-note {{undefined function 'f' cannot be used in a constant expression}} +static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}} expected-note {{undefined function 'g' cannot be used in a constant expression}} + }; +} Index: lib/AST/ExprConstant.cpp === --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -3736,7 +3736,8 @@ /// expression. static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Declaration, - const FunctionDecl *Definition) { + const FunctionDecl *Definition, + const Stmt *Body) { // Potential constant expressions can contain calls to declared, but not yet // defined, constexpr functions. if (Info.checkingPotentialConstantExpression() && !Definition && @@ -3749,7 +3750,8 @@ return false; // Can we evaluate this function call? - if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) + if (Definition && Definition->isConstexpr() && + !Definition->isInvalidDecl() && Body) return true; if (Info.getLangOpts().CPlusPlus11) { @@ -4275,7 +4277,7 @@ const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); -if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) || +if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; @@ -5483,9 +5485,9 @@ } const FunctionDecl *Definition = nullptr; - FD->getBody(Definition); + auto Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; // Avoid materializing a temporary for an elidable copy/move constructor. @@ -5971,9 +5973,9 @@ } const FunctionDecl *Definition = nullptr; - FD->getBody(Definition); + auto Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; if (ZeroInit && !HadZeroInit) { Index: test/SemaCXX/constant-expression-cxx11.cpp === --- test/SemaCXX/constant-expression-cxx11.cpp +++ test/SemaCXX/constant-expression-cxx11.cpp @@ -2005,3 +2005,13 @@ constexpr int a = *f().p; constexpr int b = *g().p; } + +namespace IncompleteClass { + struct XX { +static constexpr int f(XX*) { return 1; } // expected-note {{here}} +friend constexpr int g(XX*) { return 2; } // expected-note {{here}} + +static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}} expected-note {{undefined function 'f' cannot be used in a constant expression}} +static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}} expected-note {{undefined function 'g' cannot be used in a constant expression}} + }; +} Index: lib/AST/ExprConstant.cpp === --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -3736,7 +3736,8 @@ /// expression. static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Declaration, - const FunctionDecl *Definition) { + const FunctionDecl *Definition, + const Stmt *Body) { // Potential constant expressions can contain calls to declared, but not yet // defined, constexpr functions
Re: [PATCH] D16973: Fix ICE with constexpr and friend functions
ogoffart added a comment. ping? http://reviews.llvm.org/D16973 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r260675 - Fix ICE with constexpr and friend functions
Author: ogoffart Date: Fri Feb 12 06:34:44 2016 New Revision: 260675 URL: http://llvm.org/viewvc/llvm-project?rev=260675&view=rev Log: Fix ICE with constexpr and friend functions Fix a crash while parsing this code: struct X { friend constexpr int foo(X*) { return 12; } static constexpr int j = foo(static_cast(nullptr)); }; Differential Revision: http://reviews.llvm.org/D16973 Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=260675&r1=260674&r2=260675&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Feb 12 06:34:44 2016 @@ -3736,7 +3736,8 @@ static bool CheckTrivialDefaultConstruct /// expression. static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Declaration, - const FunctionDecl *Definition) { + const FunctionDecl *Definition, + const Stmt *Body) { // Potential constant expressions can contain calls to declared, but not yet // defined, constexpr functions. if (Info.checkingPotentialConstantExpression() && !Definition && @@ -3749,7 +3750,8 @@ static bool CheckConstexprFunction(EvalI return false; // Can we evaluate this function call? - if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) + if (Definition && Definition->isConstexpr() && + !Definition->isInvalidDecl() && Body) return true; if (Info.getLangOpts().CPlusPlus11) { @@ -4275,7 +4277,7 @@ public: const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); -if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) || +if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; @@ -5483,9 +5485,9 @@ bool RecordExprEvaluator::VisitCXXConstr } const FunctionDecl *Definition = nullptr; - FD->getBody(Definition); + auto Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; // Avoid materializing a temporary for an elidable copy/move constructor. @@ -5971,9 +5973,9 @@ bool ArrayExprEvaluator::VisitCXXConstru } const FunctionDecl *Definition = nullptr; - FD->getBody(Definition); + auto Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; if (ZeroInit && !HadZeroInit) { Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=260675&r1=260674&r2=260675&view=diff == --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original) +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Fri Feb 12 06:34:44 2016 @@ -2005,3 +2005,13 @@ namespace PR24597 { constexpr int a = *f().p; constexpr int b = *g().p; } + +namespace IncompleteClass { + struct XX { +static constexpr int f(XX*) { return 1; } // expected-note {{here}} +friend constexpr int g(XX*) { return 2; } // expected-note {{here}} + +static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}} expected-note {{undefined function 'f' cannot be used in a constant expression}} +static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}} expected-note {{undefined function 'g' cannot be used in a constant expression}} + }; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16973: Fix ICE with constexpr and friend functions
This revision was automatically updated to reflect the committed changes. Closed by commit rL260675: Fix ICE with constexpr and friend functions (authored by ogoffart). Changed prior to commit: http://reviews.llvm.org/D16973?vs=47146&id=47791#toc Repository: rL LLVM http://reviews.llvm.org/D16973 Files: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Index: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp === --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp @@ -2005,3 +2005,13 @@ constexpr int a = *f().p; constexpr int b = *g().p; } + +namespace IncompleteClass { + struct XX { +static constexpr int f(XX*) { return 1; } // expected-note {{here}} +friend constexpr int g(XX*) { return 2; } // expected-note {{here}} + +static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}} expected-note {{undefined function 'f' cannot be used in a constant expression}} +static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}} expected-note {{undefined function 'g' cannot be used in a constant expression}} + }; +} Index: cfe/trunk/lib/AST/ExprConstant.cpp === --- cfe/trunk/lib/AST/ExprConstant.cpp +++ cfe/trunk/lib/AST/ExprConstant.cpp @@ -3736,7 +3736,8 @@ /// expression. static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Declaration, - const FunctionDecl *Definition) { + const FunctionDecl *Definition, + const Stmt *Body) { // Potential constant expressions can contain calls to declared, but not yet // defined, constexpr functions. if (Info.checkingPotentialConstantExpression() && !Definition && @@ -3749,7 +3750,8 @@ return false; // Can we evaluate this function call? - if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) + if (Definition && Definition->isConstexpr() && + !Definition->isInvalidDecl() && Body) return true; if (Info.getLangOpts().CPlusPlus11) { @@ -4275,7 +4277,7 @@ const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); -if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) || +if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; @@ -5483,9 +5485,9 @@ } const FunctionDecl *Definition = nullptr; - FD->getBody(Definition); + auto Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; // Avoid materializing a temporary for an elidable copy/move constructor. @@ -5971,9 +5973,9 @@ } const FunctionDecl *Definition = nullptr; - FD->getBody(Definition); + auto Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; if (ZeroInit && !HadZeroInit) { Index: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp === --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp @@ -2005,3 +2005,13 @@ constexpr int a = *f().p; constexpr int b = *g().p; } + +namespace IncompleteClass { + struct XX { +static constexpr int f(XX*) { return 1; } // expected-note {{here}} +friend constexpr int g(XX*) { return 2; } // expected-note {{here}} + +static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}} expected-note {{undefined function 'f' cannot be used in a constant expression}} +static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}} expected-note {{undefined function 'g' cannot be used in a constant expression}} + }; +} Index: cfe/trunk/lib/AST/ExprConstant.cpp === --- cfe/trunk/lib/AST/ExprConstant.cpp +++ cfe/trunk/lib/AST/ExprConstant.cpp @@ -3736,7 +3736,8 @@ /// expression. static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Declaration, -
Re: [PATCH] D19327: Keep invalid function body as part of the AST
ogoffart added inline comments. Comment at: lib/Sema/SemaDecl.cpp:5044-5045 @@ -5043,4 +5043,4 @@ // function template specialization, add it to the scope stack. - if (New->getDeclName() && AddToScope && - !(D.isRedeclaration() && New->isInvalidDecl())) { + if (New->getDeclName() && AddToScope && !(D.isRedeclaration() + && New->isInvalidDecl() && !D.isFunctionDefinition())) { // Only make a locally-scoped extern declaration visible if it is the first rsmith wrote: > Can we delete the invalid-decl check entirely here? If it's doing something > important, we need to figure out what and make sure we preserve that intent > if it's important, but either way it doesn't make a lot of sense to me for > this to depend on whether the declaration has a definition. I tried that, but then we have a failure in Sema/function-redecl.c and Sema/predefined-function.c int eli(float b); // expected-note {{previous declaration is here}} \ int foo() { int eli(int (int)); // expected-error {{conflicting types for 'eli'}} eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible type 'float'}} return 0; } If we keep the invalid declaration, there would not be an error in the call to eli(b) But is that a behaviour we would change? http://reviews.llvm.org/D19327 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D19763: Functions declared in a scope should not hide previous declaration in earlier scopes
ogoffart created this revision. ogoffart added reviewers: cfe-commits, rsmith. This code should be an error: void foo(int); void f3() { int foo(float); { float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} } } the foo(float) function declared at function scope should not hide the float(int) while trying to redeclare functions. http://reviews.llvm.org/D19763 Files: lib/Sema/SemaLookup.cpp test/SemaCXX/function-redecl.cpp Index: test/SemaCXX/function-redecl.cpp === --- test/SemaCXX/function-redecl.cpp +++ test/SemaCXX/function-redecl.cpp @@ -7,7 +7,7 @@ void bar(int); // expected-note 2{{previous declaration is here}} } - void foo(int); // expected-note 2{{previous declaration is here}} + void foo(int); // expected-note 3{{previous declaration is here}} void f2() { int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} @@ -25,6 +25,13 @@ } } } + + void f3() { +int foo(float); +{ + float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} +} + } } class A { Index: lib/Sema/SemaLookup.cpp === --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -1091,23 +1091,25 @@ bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { -if (NameKind == LookupRedeclarationWithLinkage) { - // Determine whether this (or a previous) declaration is - // out-of-scope. - if (!LeftStartingScope && !Initial->isDeclScope(*I)) -LeftStartingScope = true; - - // If we found something outside of our starting scope that - // does not have linkage, skip it. If it's a template parameter, +if (NameKind == LookupRedeclarationWithLinkage && +!(*I)->isTemplateParameter()) { + // If it's a template parameter, // we still find it, so we can diagnose the invalid redeclaration. - if (LeftStartingScope && !((*I)->hasLinkage()) && - !(*I)->isTemplateParameter()) { + + // Determine whether this (or a previous) declaration is + // out-of-scope. + if (!LeftStartingScope && !Initial->isDeclScope(*I)) +LeftStartingScope = true; + + // If we found something outside of our starting scope that + // does not have linkage, skip it. + if (LeftStartingScope && !((*I)->hasLinkage())) { R.setShadowed(); continue; } +} else { + Found = true; } - -Found = true; R.addDecl(ND); } } Index: test/SemaCXX/function-redecl.cpp === --- test/SemaCXX/function-redecl.cpp +++ test/SemaCXX/function-redecl.cpp @@ -7,7 +7,7 @@ void bar(int); // expected-note 2{{previous declaration is here}} } - void foo(int); // expected-note 2{{previous declaration is here}} + void foo(int); // expected-note 3{{previous declaration is here}} void f2() { int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} @@ -25,6 +25,13 @@ } } } + + void f3() { +int foo(float); +{ + float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} +} + } } class A { Index: lib/Sema/SemaLookup.cpp === --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -1091,23 +1091,25 @@ bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { -if (NameKind == LookupRedeclarationWithLinkage) { - // Determine whether this (or a previous) declaration is - // out-of-scope. - if (!LeftStartingScope && !Initial->isDeclScope(*I)) -LeftStartingScope = true; - - // If we found something outside of our starting scope that - // does not have linkage, skip it. If it's a template parameter, +if (NameKind == LookupRedeclarationWithLinkage && +!(*I)->isTemplateParameter()) { + // If it's a template parameter, // we still find it, so we can diagnose the invalid redeclaration. - if (LeftStartingScope && !((*I)->hasLinkage()) && - !(*I)->isTemplateParameter()) { + + // Determine whether this (or a previous) declaration is + // out-of-scope. + if (!LeftStartingScope && !Initial->isDeclScope(*I)) +LeftStartingScope = true; + + // If we found something outside of our starting scope that +
[PATCH] D19764: Keep invalid functions as part of the AST
ogoffart created this revision. ogoffart added reviewers: cfe-commits, rsmith. This is an alternative to http://reviews.llvm.org/D19327 We want to keep all the invalid function declarations as part of the AST. This patch depends also on http://reviews.llvm.org/D19763 otherwise the tests in SemaCXX/function)redecl.cxx would fail as some invalid declarations would be hiding previous ones, preventing errors http://reviews.llvm.org/D19764 Files: lib/Sema/SemaDecl.cpp test/Misc/ast-dump-invalid.cpp test/Sema/predefined-function.c Index: test/Sema/predefined-function.c === --- test/Sema/predefined-function.c +++ test/Sema/predefined-function.c @@ -4,14 +4,13 @@ enum Test {A=-1}; char *funk(enum Test x); -int eli(float b); // expected-note {{previous declaration is here}} \ -// expected-note{{passing argument to parameter 'b' here}} +int eli(float b); // expected-note {{previous declaration is here}} int b(int c) {return 1;} int foo(); int foo() { int eli(int (int)); // expected-error {{conflicting types for 'eli'}} - eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible type 'float'}} + eli(b); return 0; } Index: test/Misc/ast-dump-invalid.cpp === --- test/Misc/ast-dump-invalid.cpp +++ test/Misc/ast-dump-invalid.cpp @@ -41,3 +41,24 @@ // CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + +namespace TestInvalidFunctionDecl { +struct Str { + double foo1(double, invalid_type); +}; +double Str::foo1(double, invalid_type) +{ return 45; } +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl +// CHECK-NEXT: |-CXXRecordDecl {{.*}} line:46:8 struct Str definition +// CHECK-NEXT: | |-CXXRecordDecl {{.*}} col:8 implicit struct Str +// CHECK-NEXT: | `-CXXMethodDecl {{.*}} col:11 invalid foo1 'double (double, int)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} col:22 'double' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} > col:36 invalid 'int' +// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}} line:49:13 invalid foo1 'double (double, int)' +// CHECK-NEXT: |-ParmVarDecl {{.*}} col:24 'double' +// CHECK-NEXT: |-ParmVarDecl {{.*}} > col:38 invalid 'int' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 45 Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -5049,10 +5049,9 @@ if (!New) return nullptr; - // If this has an identifier and is not an invalid redeclaration or - // function template specialization, add it to the scope stack. - if (New->getDeclName() && AddToScope && - !(D.isRedeclaration() && New->isInvalidDecl())) { + // If this has an identifier and is not a function template specialization, + // add it to the scope stack. + if (New->getDeclName() && AddToScope) { // Only make a locally-scoped extern declaration visible if it is the first // declaration of this entity. Qualified lookup for such an entity should // only find this declaration if there is no visible declaration of it. Index: test/Sema/predefined-function.c === --- test/Sema/predefined-function.c +++ test/Sema/predefined-function.c @@ -4,14 +4,13 @@ enum Test {A=-1}; char *funk(enum Test x); -int eli(float b); // expected-note {{previous declaration is here}} \ -// expected-note{{passing argument to parameter 'b' here}} +int eli(float b); // expected-note {{previous declaration is here}} int b(int c) {return 1;} int foo(); int foo() { int eli(int (int)); // expected-error {{conflicting types for 'eli'}} - eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible type 'float'}} + eli(b); return 0; } Index: test/Misc/ast-dump-invalid.cpp === --- test/Misc/ast-dump-invalid.cpp +++ test/Misc/ast-dump-invalid.cpp @@ -41,3 +41,24 @@ // CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + +namespace TestInvalidFunctionDecl { +struct Str { + double foo1(double, invalid_type); +}; +double Str::foo1(double, invalid_type) +{ return 45; } +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl +// CHECK-NEXT: |-CXXRecordDecl {{.*}} line:46:8 struct Str definition +// CHECK-NEXT: | |-CXXRecordDecl {{.*}} col:8 implicit struct Str +// CHECK-NEXT: | `-CXXMethodDecl {{.*}} col:11 invalid foo1 'double (double, int)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} col:22 'double' +// CHECK-NEXT: | `-ParmVarDec
Re: [PATCH] D19327: Keep invalid function body as part of the AST
ogoffart added a comment. An alternative patch is uploaded there: http://reviews.llvm.org/D19764 http://reviews.llvm.org/D19327 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D19764: Keep invalid functions as part of the AST
ogoffart added a comment. Ping? http://reviews.llvm.org/D19764 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D20054: Fix spurious warnings about unused private field
ogoffart created this revision. ogoffart added reviewers: cfe-commits, djasper. If the address of a field is taken as a pointer to member, we should not warn that the field is not used. Normaly, yse of fields are done from MemberExpr, but in case of pointer to member, it is in a DeclRefExpr http://reviews.llvm.org/D20054 Files: lib/Sema/SemaExpr.cpp test/SemaCXX/warn-unused-private-field.cpp Index: test/SemaCXX/warn-unused-private-field.cpp === --- test/SemaCXX/warn-unused-private-field.cpp +++ test/SemaCXX/warn-unused-private-field.cpp @@ -128,6 +128,7 @@ int *use = &by_reference_; int test[2]; test[as_array_index_] = 42; +int EverythingUsed::*ptr = &EverythingUsed::by_pointer_to_member_; } template @@ -142,6 +143,7 @@ int by_template_function_; int as_array_index_; int by_initializer_; + int by_pointer_to_member_; }; class HasFeatureTest { Index: lib/Sema/SemaExpr.cpp === --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -1736,10 +1736,12 @@ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) recordUseOfEvaluatedWeak(E); - // Just in case we're building an illegal pointer-to-member. - FieldDecl *FD = dyn_cast(D); - if (FD && FD->isBitField()) -E->setObjectKind(OK_BitField); + if (FieldDecl *FD = dyn_cast(D)) { +UnusedPrivateFields.remove(FD); +// Just in case we're building an illegal pointer-to-member. +if (FD->isBitField()) + E->setObjectKind(OK_BitField); + } return E; } Index: test/SemaCXX/warn-unused-private-field.cpp === --- test/SemaCXX/warn-unused-private-field.cpp +++ test/SemaCXX/warn-unused-private-field.cpp @@ -128,6 +128,7 @@ int *use = &by_reference_; int test[2]; test[as_array_index_] = 42; +int EverythingUsed::*ptr = &EverythingUsed::by_pointer_to_member_; } template @@ -142,6 +143,7 @@ int by_template_function_; int as_array_index_; int by_initializer_; + int by_pointer_to_member_; }; class HasFeatureTest { Index: lib/Sema/SemaExpr.cpp === --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -1736,10 +1736,12 @@ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) recordUseOfEvaluatedWeak(E); - // Just in case we're building an illegal pointer-to-member. - FieldDecl *FD = dyn_cast(D); - if (FD && FD->isBitField()) -E->setObjectKind(OK_BitField); + if (FieldDecl *FD = dyn_cast(D)) { +UnusedPrivateFields.remove(FD); +// Just in case we're building an illegal pointer-to-member. +if (FD->isBitField()) + E->setObjectKind(OK_BitField); + } return E; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r268895 - Fix spurious warnings about unused private field
Author: ogoffart Date: Mon May 9 02:09:51 2016 New Revision: 268895 URL: http://llvm.org/viewvc/llvm-project?rev=268895&view=rev Log: Fix spurious warnings about unused private field If the address of a field is taken as a pointer to member, we should not warn that the field is not used. Normaly, yse of fields are done from MemberExpr, but in case of pointer to member, it is in a DeclRefExpr Differential Revision: http://reviews.llvm.org/D20054 Modified: cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=268895&r1=268894&r2=268895&view=diff == --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon May 9 02:09:51 2016 @@ -1736,10 +1736,12 @@ Sema::BuildDeclRefExpr(ValueDecl *D, Qua !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) recordUseOfEvaluatedWeak(E); - // Just in case we're building an illegal pointer-to-member. - FieldDecl *FD = dyn_cast(D); - if (FD && FD->isBitField()) -E->setObjectKind(OK_BitField); + if (FieldDecl *FD = dyn_cast(D)) { +UnusedPrivateFields.remove(FD); +// Just in case we're building an illegal pointer-to-member. +if (FD->isBitField()) + E->setObjectKind(OK_BitField); + } return E; } Modified: cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp?rev=268895&r1=268894&r2=268895&view=diff == --- cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp Mon May 9 02:09:51 2016 @@ -128,6 +128,7 @@ class EverythingUsed { int *use = &by_reference_; int test[2]; test[as_array_index_] = 42; +int EverythingUsed::*ptr = &EverythingUsed::by_pointer_to_member_; } template @@ -142,6 +143,7 @@ class EverythingUsed { int by_template_function_; int as_array_index_; int by_initializer_; + int by_pointer_to_member_; }; class HasFeatureTest { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20054: Fix spurious warnings about unused private field
This revision was automatically updated to reflect the committed changes. Closed by commit rL268895: Fix spurious warnings about unused private field (authored by ogoffart). Changed prior to commit: http://reviews.llvm.org/D20054?vs=56514&id=56530#toc Repository: rL LLVM http://reviews.llvm.org/D20054 Files: cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp Index: cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp === --- cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp +++ cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp @@ -128,6 +128,7 @@ int *use = &by_reference_; int test[2]; test[as_array_index_] = 42; +int EverythingUsed::*ptr = &EverythingUsed::by_pointer_to_member_; } template @@ -142,6 +143,7 @@ int by_template_function_; int as_array_index_; int by_initializer_; + int by_pointer_to_member_; }; class HasFeatureTest { Index: cfe/trunk/lib/Sema/SemaExpr.cpp === --- cfe/trunk/lib/Sema/SemaExpr.cpp +++ cfe/trunk/lib/Sema/SemaExpr.cpp @@ -1736,10 +1736,12 @@ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) recordUseOfEvaluatedWeak(E); - // Just in case we're building an illegal pointer-to-member. - FieldDecl *FD = dyn_cast(D); - if (FD && FD->isBitField()) -E->setObjectKind(OK_BitField); + if (FieldDecl *FD = dyn_cast(D)) { +UnusedPrivateFields.remove(FD); +// Just in case we're building an illegal pointer-to-member. +if (FD->isBitField()) + E->setObjectKind(OK_BitField); + } return E; } Index: cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp === --- cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp +++ cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp @@ -128,6 +128,7 @@ int *use = &by_reference_; int test[2]; test[as_array_index_] = 42; +int EverythingUsed::*ptr = &EverythingUsed::by_pointer_to_member_; } template @@ -142,6 +143,7 @@ int by_template_function_; int as_array_index_; int by_initializer_; + int by_pointer_to_member_; }; class HasFeatureTest { Index: cfe/trunk/lib/Sema/SemaExpr.cpp === --- cfe/trunk/lib/Sema/SemaExpr.cpp +++ cfe/trunk/lib/Sema/SemaExpr.cpp @@ -1736,10 +1736,12 @@ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) recordUseOfEvaluatedWeak(E); - // Just in case we're building an illegal pointer-to-member. - FieldDecl *FD = dyn_cast(D); - if (FD && FD->isBitField()) -E->setObjectKind(OK_BitField); + if (FieldDecl *FD = dyn_cast(D)) { +UnusedPrivateFields.remove(FD); +// Just in case we're building an illegal pointer-to-member. +if (FD->isBitField()) + E->setObjectKind(OK_BitField); + } return E; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18080: CIndex: add support for static_assert
ogoffart added a comment. Ping? http://reviews.llvm.org/D18080 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18081: Make sizeof and alignof a CXCursor_UnaryExpr
ogoffart added a comment. Ping? http://reviews.llvm.org/D18081 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D19327: Keep invalid function body as part of the AST
ogoffart created this revision. ogoffart added reviewers: cfe-commits, rsmith. struct XX { double foo(invalid_type xx); }; double XX::foo(invalid_type xx) { return 45; } We should keep XX::foo and its function body as part of the AST so tools can still do something with the body even if the definition is wrong. Inline function would already be kept, but not when they are redeclarations. http://reviews.llvm.org/D19327 Files: lib/Sema/SemaDecl.cpp test/Misc/ast-dump-invalid.cpp Index: test/Misc/ast-dump-invalid.cpp === --- test/Misc/ast-dump-invalid.cpp +++ test/Misc/ast-dump-invalid.cpp @@ -41,3 +41,24 @@ // CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + +namespace TestInvalidFunctionDecl { +struct Str { + double foo1(double, invalid_type); +}; +double Str::foo1(double, invalid_type) +{ return 45; } +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl +// CHECK-NEXT: |-CXXRecordDecl {{.*}} line:46:8 struct Str definition +// CHECK-NEXT: | |-CXXRecordDecl {{.*}} col:8 implicit struct Str +// CHECK-NEXT: | `-CXXMethodDecl {{.*}} col:11 invalid foo1 'double (double, int)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} col:22 'double' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} > col:36 invalid 'int' +// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}} line:49:13 invalid foo1 'double (double, int)' +// CHECK-NEXT: |-ParmVarDecl {{.*}} col:24 'double' +// CHECK-NEXT: |-ParmVarDecl {{.*}} > col:38 invalid 'int' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 45 Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -5041,8 +5041,8 @@ // If this has an identifier and is not an invalid redeclaration or // function template specialization, add it to the scope stack. - if (New->getDeclName() && AddToScope && - !(D.isRedeclaration() && New->isInvalidDecl())) { + if (New->getDeclName() && AddToScope && !(D.isRedeclaration() + && New->isInvalidDecl() && !D.isFunctionDefinition())) { // Only make a locally-scoped extern declaration visible if it is the first // declaration of this entity. Qualified lookup for such an entity should // only find this declaration if there is no visible declaration of it. Index: test/Misc/ast-dump-invalid.cpp === --- test/Misc/ast-dump-invalid.cpp +++ test/Misc/ast-dump-invalid.cpp @@ -41,3 +41,24 @@ // CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + +namespace TestInvalidFunctionDecl { +struct Str { + double foo1(double, invalid_type); +}; +double Str::foo1(double, invalid_type) +{ return 45; } +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl +// CHECK-NEXT: |-CXXRecordDecl {{.*}} line:46:8 struct Str definition +// CHECK-NEXT: | |-CXXRecordDecl {{.*}} col:8 implicit struct Str +// CHECK-NEXT: | `-CXXMethodDecl {{.*}} col:11 invalid foo1 'double (double, int)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} col:22 'double' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} > col:36 invalid 'int' +// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}} line:49:13 invalid foo1 'double (double, int)' +// CHECK-NEXT: |-ParmVarDecl {{.*}} col:24 'double' +// CHECK-NEXT: |-ParmVarDecl {{.*}} > col:38 invalid 'int' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 45 Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -5041,8 +5041,8 @@ // If this has an identifier and is not an invalid redeclaration or // function template specialization, add it to the scope stack. - if (New->getDeclName() && AddToScope && - !(D.isRedeclaration() && New->isInvalidDecl())) { + if (New->getDeclName() && AddToScope && !(D.isRedeclaration() + && New->isInvalidDecl() && !D.isFunctionDefinition())) { // Only make a locally-scoped extern declaration visible if it is the first // declaration of this entity. Qualified lookup for such an entity should // only find this declaration if there is no visible declaration of it. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D19327: Keep invalid function body as part of the AST
ogoffart added a comment. Ping? http://reviews.llvm.org/D19327 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D20511: Fix crash while parsing variable template with variadic template arguments
ogoffart created this revision. ogoffart added reviewers: cfe-commits, rsmith. It is only a crash if the compiler optimize for this!=nullptr because LocalInstantiationScope::getPartiallySubstitutedPack checks if 'this' is null. (This is crashing when clang is compiled with GCC6) http://reviews.llvm.org/D20511 Files: lib/Sema/SemaTemplateVariadic.cpp test/SemaCXX/cxx1y-variable-templates_top_level.cpp Index: test/SemaCXX/cxx1y-variable-templates_top_level.cpp === --- test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -458,3 +458,9 @@ template<> int g; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}} } +#ifndef PRECXX11 +template struct Variadic_t { }; +template Variadic_t Variadic; +auto variadic1 = Variadic<>; +auto variadic2 = Variadic; +#endif Index: lib/Sema/SemaTemplateVariadic.cpp === --- lib/Sema/SemaTemplateVariadic.cpp +++ lib/Sema/SemaTemplateVariadic.cpp @@ -604,7 +604,7 @@ // Template argument deduction can extend the sequence of template // arguments corresponding to a template parameter pack, even when the // sequence contains explicitly specified template arguments. -if (!IsFunctionParameterPack) { +if (!IsFunctionParameterPack && CurrentInstantiationScope) { if (NamedDecl *PartialPack = CurrentInstantiationScope->getPartiallySubstitutedPack()){ unsigned PartialDepth, PartialIndex; Index: test/SemaCXX/cxx1y-variable-templates_top_level.cpp === --- test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -458,3 +458,9 @@ template<> int g; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}} } +#ifndef PRECXX11 +template struct Variadic_t { }; +template Variadic_t Variadic; +auto variadic1 = Variadic<>; +auto variadic2 = Variadic; +#endif Index: lib/Sema/SemaTemplateVariadic.cpp === --- lib/Sema/SemaTemplateVariadic.cpp +++ lib/Sema/SemaTemplateVariadic.cpp @@ -604,7 +604,7 @@ // Template argument deduction can extend the sequence of template // arguments corresponding to a template parameter pack, even when the // sequence contains explicitly specified template arguments. -if (!IsFunctionParameterPack) { +if (!IsFunctionParameterPack && CurrentInstantiationScope) { if (NamedDecl *PartialPack = CurrentInstantiationScope->getPartiallySubstitutedPack()){ unsigned PartialDepth, PartialIndex; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D19327: Keep invalid function body as part of the AST
ogoffart added a comment. Is this better than the alternative http://reviews.llvm.org/D19764 ? http://reviews.llvm.org/D19327 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20511: Fix crash while parsing variable template with variadic template arguments
ogoffart added a comment. I believe this is trivial so i will just commit it. http://reviews.llvm.org/D20511 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r270845 - Fix crash while parsing variable template with variadic template arguments
Author: ogoffart Date: Thu May 26 07:55:34 2016 New Revision: 270845 URL: http://llvm.org/viewvc/llvm-project?rev=270845&view=rev Log: Fix crash while parsing variable template with variadic template arguments It is only a crash if the compiler optimize for this!=nullptr because LocalInstantiationScope::getPartiallySubstitutedPack checks if 'this' is null (This is crashing when clang is compiled with GCC6) Differential Revision: http://reviews.llvm.org/D20511 Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=270845&r1=270844&r2=270845&view=diff == --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Thu May 26 07:55:34 2016 @@ -604,7 +604,7 @@ bool Sema::CheckParameterPacksForExpansi // Template argument deduction can extend the sequence of template // arguments corresponding to a template parameter pack, even when the // sequence contains explicitly specified template arguments. -if (!IsFunctionParameterPack) { +if (!IsFunctionParameterPack && CurrentInstantiationScope) { if (NamedDecl *PartialPack = CurrentInstantiationScope->getPartiallySubstitutedPack()){ unsigned PartialDepth, PartialIndex; Modified: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp?rev=270845&r1=270844&r2=270845&view=diff == --- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp Thu May 26 07:55:34 2016 @@ -458,3 +458,9 @@ namespace PR19169 { template<> int g; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}} } +#ifndef PRECXX11 +template struct Variadic_t { }; +template Variadic_t Variadic; +auto variadic1 = Variadic<>; +auto variadic2 = Variadic; +#endif ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20511: Fix crash while parsing variable template with variadic template arguments
This revision was automatically updated to reflect the committed changes. Closed by commit rL270845: Fix crash while parsing variable template with variadic template arguments (authored by ogoffart). Changed prior to commit: http://reviews.llvm.org/D20511?vs=58043&id=58595#toc Repository: rL LLVM http://reviews.llvm.org/D20511 Files: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp Index: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp === --- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -458,3 +458,9 @@ template<> int g; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}} } +#ifndef PRECXX11 +template struct Variadic_t { }; +template Variadic_t Variadic; +auto variadic1 = Variadic<>; +auto variadic2 = Variadic; +#endif Index: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp === --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp @@ -604,7 +604,7 @@ // Template argument deduction can extend the sequence of template // arguments corresponding to a template parameter pack, even when the // sequence contains explicitly specified template arguments. -if (!IsFunctionParameterPack) { +if (!IsFunctionParameterPack && CurrentInstantiationScope) { if (NamedDecl *PartialPack = CurrentInstantiationScope->getPartiallySubstitutedPack()){ unsigned PartialDepth, PartialIndex; Index: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp === --- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -458,3 +458,9 @@ template<> int g; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}} } +#ifndef PRECXX11 +template struct Variadic_t { }; +template Variadic_t Variadic; +auto variadic1 = Variadic<>; +auto variadic2 = Variadic; +#endif Index: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp === --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp @@ -604,7 +604,7 @@ // Template argument deduction can extend the sequence of template // arguments corresponding to a template parameter pack, even when the // sequence contains explicitly specified template arguments. -if (!IsFunctionParameterPack) { +if (!IsFunctionParameterPack && CurrentInstantiationScope) { if (NamedDecl *PartialPack = CurrentInstantiationScope->getPartiallySubstitutedPack()){ unsigned PartialDepth, PartialIndex; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D20821: Fix a few issues while skipping function bodies
ogoffart created this revision. ogoffart added reviewers: cfe-commits, rsmith, akyrtzi. Herald added a subscriber: klimek. Fix a few issues while skipping function bodies - In functions with try { } catch { }, only the try block would be skipped, not the catch blocks - The template functions would still be parsed. - The initializers within a constructor would still be parsed. - The inline functions within class would still be stored, only to be discared later. - Invalid code with try would assert (as in "int foo() try assert_here") This attempt to do even less while skipping function bodies. http://reviews.llvm.org/D20821 Files: lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseStmt.cpp lib/Parse/Parser.cpp lib/Sema/SemaDecl.cpp unittests/Tooling/ToolingTest.cpp Index: unittests/Tooling/ToolingTest.cpp === --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -241,7 +241,7 @@ struct SkipBodyConsumer : public clang::ASTConsumer { /// Skip the 'skipMe' function. bool shouldSkipFunctionBody(Decl *D) override { -FunctionDecl *F = dyn_cast(D); +NamedDecl *F = dyn_cast(D); return F && F->getNameAsString() == "skipMe"; } }; @@ -259,6 +259,36 @@ "int skipMe() { an_error_here }")); EXPECT_FALSE(runToolOnCode(new SkipBodyAction, "int skipMeNot() { an_error_here }")); + + // Test constructors with initializers + EXPECT_TRUE(runToolOnCode(new SkipBodyAction, +"struct skipMe { skipMe() : an_error() { more error } };")); + EXPECT_TRUE(runToolOnCode(new SkipBodyAction, +"struct skipMe { skipMe(); };" +"skipMe::skipMe() : an_error() { more error }")); + EXPECT_FALSE(runToolOnCode(new SkipBodyAction, +"struct skipMeNot { skipMeNot() : an_error() { } };")); + EXPECT_FALSE(runToolOnCode(new SkipBodyAction, +"struct skipMeNot { skipMeNot(); };" +"skipMeNot::skipMeNot() : an_error() { }")); + + // Try/catch + EXPECT_TRUE(runToolOnCode(new SkipBodyAction, +"void skipMe() try { an_error() } catch(error) { error };")); + EXPECT_TRUE(runToolOnCode(new SkipBodyAction, +"struct S { void skipMe() try { an_error() } catch(error) { error } };")); + EXPECT_TRUE(runToolOnCode(new SkipBodyAction, +"void skipMe() try { an_error() } catch(error) { error; }" +"catch(error) { error } catch (error) { }")); + EXPECT_FALSE(runToolOnCode(new SkipBodyAction, +"void skipMe() try something;")); // don't crash while parsing + + // Template + EXPECT_TRUE(runToolOnCode(new SkipBodyAction, +"template int skipMe() { an_error_here }" +"int x = skipMe();")); + EXPECT_FALSE(runToolOnCode(new SkipBodyAction, +"template int skipMeNot() { an_error_here }")); } TEST(runToolOnCodeWithArgs, TestNoDepFile) { Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -11378,7 +11378,7 @@ FD->setHasSkippedBody(); else if (ObjCMethodDecl *MD = dyn_cast_or_null(Decl)) MD->setHasSkippedBody(); - return ActOnFinishFunctionBody(Decl, nullptr); + return Decl; } Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { Index: lib/Parse/Parser.cpp === --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -1044,6 +1044,12 @@ D.complete(DP); D.getMutableDeclSpec().abort(); +if (SkipFunctionBodies && (!DP || Actions.canSkipFunctionBody(DP)) && +trySkippingFunctionBody()) { + BodyScope.Exit(); + return Actions.ActOnSkippedFunctionBody(DP); +} + CachedTokens Toks; LexTemplateFunctionForLateParsing(Toks); @@ -1136,6 +1142,13 @@ return Res; } + if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) && + trySkippingFunctionBody()) { +BodyScope.Exit(); +Actions.ActOnSkippedFunctionBody(Res); +return Actions.ActOnFinishFunctionBody(Res, nullptr, false); + } + if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res, BodyScope); Index: lib/Parse/ParseStmt.cpp === --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -1916,12 +1916,6 @@ assert(Tok.is(tok::l_brace)); SourceLocation LBraceLoc = Tok.getLocation(); - if (SkipFunctionBodies && (!Decl || Actions.canSkipFunctionBody(Decl)) && - trySkippingFunctionBody()) { -BodyScope.Exit(); -return Actions.ActOnSkippedFunctionBody(Decl); - } - PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, "parsing function body"); @@ -1964,12 +1958,6 @@ else Actions.ActOnDefaultCtorInitializers(Decl); - if (SkipFunctionBodies && Actions.canSkipFunctionBody(Decl) && - trySkippingFunctionBody(
Re: [PATCH] D20821: Fix a few issues while skipping function bodies
ogoffart updated this revision to Diff 59197. ogoffart added a comment. Right, i forgot about the C++11 initializer list syntax. I hope I got it right now. http://reviews.llvm.org/D20821 Files: lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseStmt.cpp lib/Parse/Parser.cpp lib/Sema/SemaDecl.cpp unittests/Tooling/ToolingTest.cpp Index: unittests/Tooling/ToolingTest.cpp === --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -241,7 +241,7 @@ struct SkipBodyConsumer : public clang::ASTConsumer { /// Skip the 'skipMe' function. bool shouldSkipFunctionBody(Decl *D) override { -FunctionDecl *F = dyn_cast(D); +NamedDecl *F = dyn_cast(D); return F && F->getNameAsString() == "skipMe"; } }; @@ -259,6 +259,56 @@ "int skipMe() { an_error_here }")); EXPECT_FALSE(runToolOnCode(new SkipBodyAction, "int skipMeNot() { an_error_here }")); + + // Test constructors with initializers + EXPECT_TRUE( + runToolOnCode(new SkipBodyAction, +"struct skipMe { skipMe() : an_error() { more error } };")); + EXPECT_TRUE( + runToolOnCode(new SkipBodyAction, +"struct skipMe { skipMe(); };" +"skipMe::skipMe() : an_error([](){;}) { more error }")); + EXPECT_TRUE( + runToolOnCode(new SkipBodyAction, +"struct skipMe { skipMe(); };" +"skipMe::skipMe() : an_error{[](){;}} { more error }")); + EXPECT_TRUE( + runToolOnCode(new SkipBodyAction, +"struct skipMe { skipMe(); };" +"skipMe::skipMe() : a(e)>>(), f{}, g() { error }")); + EXPECT_TRUE( + runToolOnCode(new SkipBodyAction, +"struct skipMe { skipMe() : bases()... { error } };")); + + EXPECT_FALSE( + runToolOnCode(new SkipBodyAction, +"struct skipMeNot { skipMeNot() : an_error() { } };")); + EXPECT_FALSE(runToolOnCode(new SkipBodyAction, + "struct skipMeNot { skipMeNot(); };" + "skipMeNot::skipMeNot() : an_error() { }")); + + // Try/catch + EXPECT_TRUE(runToolOnCode( + new SkipBodyAction, + "void skipMe() try { an_error() } catch(error) { error };")); + EXPECT_TRUE(runToolOnCode( + new SkipBodyAction, + "struct S { void skipMe() try { an_error() } catch(error) { error } };")); + EXPECT_TRUE( + runToolOnCode(new SkipBodyAction, +"void skipMe() try { an_error() } catch(error) { error; }" +"catch(error) { error } catch (error) { }")); + EXPECT_FALSE(runToolOnCode( + new SkipBodyAction, + "void skipMe() try something;")); // don't crash while parsing + + // Template + EXPECT_TRUE(runToolOnCode( + new SkipBodyAction, "template int skipMe() { an_error_here }" + "int x = skipMe();")); + EXPECT_FALSE( + runToolOnCode(new SkipBodyAction, +"template int skipMeNot() { an_error_here }")); } TEST(runToolOnCodeWithArgs, TestNoDepFile) { Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -11378,7 +11378,7 @@ FD->setHasSkippedBody(); else if (ObjCMethodDecl *MD = dyn_cast_or_null(Decl)) MD->setHasSkippedBody(); - return ActOnFinishFunctionBody(Decl, nullptr); + return Decl; } Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { Index: lib/Parse/Parser.cpp === --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -1044,6 +1044,12 @@ D.complete(DP); D.getMutableDeclSpec().abort(); +if (SkipFunctionBodies && (!DP || Actions.canSkipFunctionBody(DP)) && +trySkippingFunctionBody()) { + BodyScope.Exit(); + return Actions.ActOnSkippedFunctionBody(DP); +} + CachedTokens Toks; LexTemplateFunctionForLateParsing(Toks); @@ -1136,6 +1142,13 @@ return Res; } + if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) && + trySkippingFunctionBody()) { +BodyScope.Exit(); +Actions.ActOnSkippedFunctionBody(Res); +return Actions.ActOnFinishFunctionBody(Res, nullptr, false); + } + if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res, BodyScope); Index: lib/Parse/ParseStmt.cpp === --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -1916,12 +1916,6 @@ assert(Tok.is(tok::l_brace)); SourceLocation LBraceLoc = Tok.getLocation(); - if (SkipFunctionBodies && (!Decl || Actions.canSkipFunctionBody(Decl)) && - trySkippingFunctionBody()) { -BodyScope.Exit(); -return Actions.ActOnSkippedFunctionBody(Decl); - } - PrettyDeclStackTrace
Re: [PATCH] D18080: CIndex: add support for static_assert
ogoffart added a comment. Ping 2. http://reviews.llvm.org/D18080 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18081: Make sizeof and alignof a CXCursor_UnaryExpr
ogoffart added a comment. Ping 2. http://reviews.llvm.org/D18081 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D19763: Functions declared in a scope should not hide previous declaration in earlier scopes
ogoffart added a comment. Ping. This would be required for http://reviews.llvm.org/D19764 http://reviews.llvm.org/D19763 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20821: Fix a few issues while skipping function bodies
ogoffart added a comment. The idea is that when we see a ") {" or "} {" in the ctor-initializers, (optionally with "..."), it is necessarily the start of the body. Unless there might be lambda expressions within a template aregument, as in: A::A() : Base<[](){return 42; }()>(){} But this is not valid because lambda expression cannot appear in this context as far as i know since lambda expression cannot appear in template argument http://reviews.llvm.org/D20821 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r272273 - CIndex: add support for static_assert
Author: ogoffart Date: Thu Jun 9 11:15:55 2016 New Revision: 272273 URL: http://llvm.org/viewvc/llvm-project?rev=272273&view=rev Log: CIndex: add support for static_assert Differential Revision: http://reviews.llvm.org/D18080 Modified: cfe/trunk/include/clang-c/Index.h cfe/trunk/lib/Sema/SemaCodeComplete.cpp cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/tools/libclang/CursorVisitor.h Modified: cfe/trunk/include/clang-c/Index.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=272273&r1=272272&r2=272273&view=diff == --- cfe/trunk/include/clang-c/Index.h (original) +++ cfe/trunk/include/clang-c/Index.h Thu Jun 9 11:15:55 2016 @@ -2359,8 +2359,12 @@ enum CXCursorKind { */ CXCursor_ModuleImportDecl = 600, CXCursor_TypeAliasTemplateDecl = 601, + /** + * \brief A static_assert or _Static_assert node + */ + CXCursor_StaticAssert = 602, CXCursor_FirstExtraDecl= CXCursor_ModuleImportDecl, - CXCursor_LastExtraDecl = CXCursor_TypeAliasTemplateDecl, + CXCursor_LastExtraDecl = CXCursor_StaticAssert, /** * \brief A code completion overload candidate. Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=272273&r1=272272&r2=272273&view=diff == --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original) +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Thu Jun 9 11:15:55 2016 @@ -3044,6 +3044,7 @@ CXCursorKind clang::getCursorKindForDecl case Decl::ClassTemplatePartialSpecialization: return CXCursor_ClassTemplatePartialSpecialization; case Decl::UsingDirective: return CXCursor_UsingDirective; +case Decl::StaticAssert: return CXCursor_StaticAssert; case Decl::TranslationUnit:return CXCursor_TranslationUnit; case Decl::Using: Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=272273&r1=272272&r2=272273&view=diff == --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Thu Jun 9 11:15:55 2016 @@ -1230,6 +1230,14 @@ bool CursorVisitor::VisitUnresolvedUsing return false; } +bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) { + if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, RegionOfInterest))) +return true; + if (Visit(MakeCXCursor(D->getMessage(), StmtParent, TU, RegionOfInterest))) +return true; + return false; +} + bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) { switch (Name.getName().getNameKind()) { case clang::DeclarationName::Identifier: @@ -4822,6 +4830,8 @@ CXString clang_getCursorKindSpelling(enu return cxstring::createRef("OverloadCandidate"); case CXCursor_TypeAliasTemplateDecl: return cxstring::createRef("TypeAliasTemplateDecl"); + case CXCursor_StaticAssert: + return cxstring::createRef("StaticAssert"); } llvm_unreachable("Unhandled CXCursorKind"); Modified: cfe/trunk/tools/libclang/CursorVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CursorVisitor.h?rev=272273&r1=272272&r2=272273&view=diff == --- cfe/trunk/tools/libclang/CursorVisitor.h (original) +++ cfe/trunk/tools/libclang/CursorVisitor.h Thu Jun 9 11:15:55 2016 @@ -238,6 +238,7 @@ public: bool VisitUsingDecl(UsingDecl *D); bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + bool VisitStaticAssertDecl(StaticAssertDecl *D); // Name visitor bool VisitDeclarationNameInfo(DeclarationNameInfo Name); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r272274 - Make sizeof and alignof a CXCursor_UnaryExpr
Author: ogoffart Date: Thu Jun 9 11:16:06 2016 New Revision: 272274 URL: http://llvm.org/viewvc/llvm-project?rev=272274&view=rev Log: Make sizeof and alignof a CXCursor_UnaryExpr So we can match sizeof expressions more accurately than with UnexposedExpr Differential Revision: http://reviews.llvm.org/D18081 Modified: cfe/trunk/include/clang-c/Index.h cfe/trunk/test/Index/annotate-tokens.c cfe/trunk/tools/libclang/CXCursor.cpp Modified: cfe/trunk/include/clang-c/Index.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=272274&r1=272273&r2=272274&view=diff == --- cfe/trunk/include/clang-c/Index.h (original) +++ cfe/trunk/include/clang-c/Index.h Thu Jun 9 11:16:06 2016 @@ -1932,7 +1932,7 @@ enum CXCursorKind { */ CXCursor_CXXDeleteExpr = 135, - /** \brief A unary expression. + /** \brief A unary expression. (noexcept, sizeof, or other traits) */ CXCursor_UnaryExpr = 136, Modified: cfe/trunk/test/Index/annotate-tokens.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-tokens.c?rev=272274&r1=272273&r2=272274&view=diff == --- cfe/trunk/test/Index/annotate-tokens.c (original) +++ cfe/trunk/test/Index/annotate-tokens.c Thu Jun 9 11:16:06 2016 @@ -80,10 +80,10 @@ void test() { // CHECK: Punctuation: "(" [5:3 - 5:4] CStyleCastExpr= // CHECK: Keyword: "void" [5:4 - 5:8] CStyleCastExpr= // CHECK: Punctuation: ")" [5:8 - 5:9] CStyleCastExpr= -// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnexposedExpr= -// CHECK: Punctuation: "(" [5:15 - 5:16] UnexposedExpr= +// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnaryExpr= +// CHECK: Punctuation: "(" [5:15 - 5:16] UnaryExpr= // CHECK: Identifier: "T" [5:16 - 5:17] TypeRef=T:1:13 -// CHECK: Punctuation: ")" [5:17 - 5:18] UnexposedExpr= +// CHECK: Punctuation: ")" [5:17 - 5:18] UnaryExpr= // CHECK: Punctuation: ";" [5:18 - 5:19] CompoundStmt= // CHECK: Keyword: "struct" [7:3 - 7:9] VarDecl=x:7:12 (Definition) // CHECK: Identifier: "X" [7:10 - 7:11] TypeRef=struct X:2:8 Modified: cfe/trunk/tools/libclang/CXCursor.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=272274&r1=272273&r2=272274&view=diff == --- cfe/trunk/tools/libclang/CXCursor.cpp (original) +++ cfe/trunk/tools/libclang/CXCursor.cpp Thu Jun 9 11:16:06 2016 @@ -256,7 +256,6 @@ CXCursor cxcursor::MakeCXCursor(const St case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: case Stmt::ConvertVectorExprClass: - case Stmt::UnaryExprOrTypeTraitExprClass: case Stmt::VAArgExprClass: case Stmt::ObjCArrayLiteralClass: case Stmt::ObjCDictionaryLiteralClass: @@ -327,6 +326,7 @@ CXCursor cxcursor::MakeCXCursor(const St K = CXCursor_UnaryOperator; break; + case Stmt::UnaryExprOrTypeTraitExprClass: case Stmt::CXXNoexceptExprClass: K = CXCursor_UnaryExpr; break; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18081: Make sizeof and alignof a CXCursor_UnaryExpr
This revision was automatically updated to reflect the committed changes. Closed by commit rL272274: Make sizeof and alignof a CXCursor_UnaryExpr (authored by ogoffart). Changed prior to commit: http://reviews.llvm.org/D18081?vs=50408&id=60187#toc Repository: rL LLVM http://reviews.llvm.org/D18081 Files: cfe/trunk/include/clang-c/Index.h cfe/trunk/test/Index/annotate-tokens.c cfe/trunk/tools/libclang/CXCursor.cpp Index: cfe/trunk/tools/libclang/CXCursor.cpp === --- cfe/trunk/tools/libclang/CXCursor.cpp +++ cfe/trunk/tools/libclang/CXCursor.cpp @@ -256,7 +256,6 @@ case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: case Stmt::ConvertVectorExprClass: - case Stmt::UnaryExprOrTypeTraitExprClass: case Stmt::VAArgExprClass: case Stmt::ObjCArrayLiteralClass: case Stmt::ObjCDictionaryLiteralClass: @@ -327,6 +326,7 @@ K = CXCursor_UnaryOperator; break; + case Stmt::UnaryExprOrTypeTraitExprClass: case Stmt::CXXNoexceptExprClass: K = CXCursor_UnaryExpr; break; Index: cfe/trunk/include/clang-c/Index.h === --- cfe/trunk/include/clang-c/Index.h +++ cfe/trunk/include/clang-c/Index.h @@ -1932,7 +1932,7 @@ */ CXCursor_CXXDeleteExpr = 135, - /** \brief A unary expression. + /** \brief A unary expression. (noexcept, sizeof, or other traits) */ CXCursor_UnaryExpr = 136, Index: cfe/trunk/test/Index/annotate-tokens.c === --- cfe/trunk/test/Index/annotate-tokens.c +++ cfe/trunk/test/Index/annotate-tokens.c @@ -80,10 +80,10 @@ // CHECK: Punctuation: "(" [5:3 - 5:4] CStyleCastExpr= // CHECK: Keyword: "void" [5:4 - 5:8] CStyleCastExpr= // CHECK: Punctuation: ")" [5:8 - 5:9] CStyleCastExpr= -// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnexposedExpr= -// CHECK: Punctuation: "(" [5:15 - 5:16] UnexposedExpr= +// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnaryExpr= +// CHECK: Punctuation: "(" [5:15 - 5:16] UnaryExpr= // CHECK: Identifier: "T" [5:16 - 5:17] TypeRef=T:1:13 -// CHECK: Punctuation: ")" [5:17 - 5:18] UnexposedExpr= +// CHECK: Punctuation: ")" [5:17 - 5:18] UnaryExpr= // CHECK: Punctuation: ";" [5:18 - 5:19] CompoundStmt= // CHECK: Keyword: "struct" [7:3 - 7:9] VarDecl=x:7:12 (Definition) // CHECK: Identifier: "X" [7:10 - 7:11] TypeRef=struct X:2:8 Index: cfe/trunk/tools/libclang/CXCursor.cpp === --- cfe/trunk/tools/libclang/CXCursor.cpp +++ cfe/trunk/tools/libclang/CXCursor.cpp @@ -256,7 +256,6 @@ case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: case Stmt::ConvertVectorExprClass: - case Stmt::UnaryExprOrTypeTraitExprClass: case Stmt::VAArgExprClass: case Stmt::ObjCArrayLiteralClass: case Stmt::ObjCDictionaryLiteralClass: @@ -327,6 +326,7 @@ K = CXCursor_UnaryOperator; break; + case Stmt::UnaryExprOrTypeTraitExprClass: case Stmt::CXXNoexceptExprClass: K = CXCursor_UnaryExpr; break; Index: cfe/trunk/include/clang-c/Index.h === --- cfe/trunk/include/clang-c/Index.h +++ cfe/trunk/include/clang-c/Index.h @@ -1932,7 +1932,7 @@ */ CXCursor_CXXDeleteExpr = 135, - /** \brief A unary expression. + /** \brief A unary expression. (noexcept, sizeof, or other traits) */ CXCursor_UnaryExpr = 136, Index: cfe/trunk/test/Index/annotate-tokens.c === --- cfe/trunk/test/Index/annotate-tokens.c +++ cfe/trunk/test/Index/annotate-tokens.c @@ -80,10 +80,10 @@ // CHECK: Punctuation: "(" [5:3 - 5:4] CStyleCastExpr= // CHECK: Keyword: "void" [5:4 - 5:8] CStyleCastExpr= // CHECK: Punctuation: ")" [5:8 - 5:9] CStyleCastExpr= -// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnexposedExpr= -// CHECK: Punctuation: "(" [5:15 - 5:16] UnexposedExpr= +// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnaryExpr= +// CHECK: Punctuation: "(" [5:15 - 5:16] UnaryExpr= // CHECK: Identifier: "T" [5:16 - 5:17] TypeRef=T:1:13 -// CHECK: Punctuation: ")" [5:17 - 5:18] UnexposedExpr= +// CHECK: Punctuation: ")" [5:17 - 5:18] UnaryExpr= // CHECK: Punctuation: ";" [5:18 - 5:19] CompoundStmt= // CHECK: Keyword: "struct" [7:3 - 7:9] VarDecl=x:7:12 (Definition) // CHECK: Identifier: "X" [7:10 - 7:11] TypeRef=struct X:2:8 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18080: CIndex: add support for static_assert
This revision was automatically updated to reflect the committed changes. Closed by commit rL272273: CIndex: add support for static_assert (authored by ogoffart). Changed prior to commit: http://reviews.llvm.org/D18080?vs=50407&id=60186#toc Repository: rL LLVM http://reviews.llvm.org/D18080 Files: cfe/trunk/include/clang-c/Index.h cfe/trunk/lib/Sema/SemaCodeComplete.cpp cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/tools/libclang/CursorVisitor.h Index: cfe/trunk/lib/Sema/SemaCodeComplete.cpp === --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp @@ -3044,6 +3044,7 @@ case Decl::ClassTemplatePartialSpecialization: return CXCursor_ClassTemplatePartialSpecialization; case Decl::UsingDirective: return CXCursor_UsingDirective; +case Decl::StaticAssert: return CXCursor_StaticAssert; case Decl::TranslationUnit:return CXCursor_TranslationUnit; case Decl::Using: Index: cfe/trunk/tools/libclang/CursorVisitor.h === --- cfe/trunk/tools/libclang/CursorVisitor.h +++ cfe/trunk/tools/libclang/CursorVisitor.h @@ -238,6 +238,7 @@ bool VisitUsingDecl(UsingDecl *D); bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + bool VisitStaticAssertDecl(StaticAssertDecl *D); // Name visitor bool VisitDeclarationNameInfo(DeclarationNameInfo Name); Index: cfe/trunk/tools/libclang/CIndex.cpp === --- cfe/trunk/tools/libclang/CIndex.cpp +++ cfe/trunk/tools/libclang/CIndex.cpp @@ -1230,6 +1230,14 @@ return false; } +bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) { + if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, RegionOfInterest))) +return true; + if (Visit(MakeCXCursor(D->getMessage(), StmtParent, TU, RegionOfInterest))) +return true; + return false; +} + bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) { switch (Name.getName().getNameKind()) { case clang::DeclarationName::Identifier: @@ -4822,6 +4830,8 @@ return cxstring::createRef("OverloadCandidate"); case CXCursor_TypeAliasTemplateDecl: return cxstring::createRef("TypeAliasTemplateDecl"); + case CXCursor_StaticAssert: + return cxstring::createRef("StaticAssert"); } llvm_unreachable("Unhandled CXCursorKind"); Index: cfe/trunk/include/clang-c/Index.h === --- cfe/trunk/include/clang-c/Index.h +++ cfe/trunk/include/clang-c/Index.h @@ -2359,8 +2359,12 @@ */ CXCursor_ModuleImportDecl = 600, CXCursor_TypeAliasTemplateDecl = 601, + /** + * \brief A static_assert or _Static_assert node + */ + CXCursor_StaticAssert = 602, CXCursor_FirstExtraDecl= CXCursor_ModuleImportDecl, - CXCursor_LastExtraDecl = CXCursor_TypeAliasTemplateDecl, + CXCursor_LastExtraDecl = CXCursor_StaticAssert, /** * \brief A code completion overload candidate. Index: cfe/trunk/lib/Sema/SemaCodeComplete.cpp === --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp @@ -3044,6 +3044,7 @@ case Decl::ClassTemplatePartialSpecialization: return CXCursor_ClassTemplatePartialSpecialization; case Decl::UsingDirective: return CXCursor_UsingDirective; +case Decl::StaticAssert: return CXCursor_StaticAssert; case Decl::TranslationUnit:return CXCursor_TranslationUnit; case Decl::Using: Index: cfe/trunk/tools/libclang/CursorVisitor.h === --- cfe/trunk/tools/libclang/CursorVisitor.h +++ cfe/trunk/tools/libclang/CursorVisitor.h @@ -238,6 +238,7 @@ bool VisitUsingDecl(UsingDecl *D); bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + bool VisitStaticAssertDecl(StaticAssertDecl *D); // Name visitor bool VisitDeclarationNameInfo(DeclarationNameInfo Name); Index: cfe/trunk/tools/libclang/CIndex.cpp === --- cfe/trunk/tools/libclang/CIndex.cpp +++ cfe/trunk/tools/libclang/CIndex.cpp @@ -1230,6 +1230,14 @@ return false; } +bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) { + if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, RegionOfInterest))) +return true; + if (Visit(MakeCXCursor(D->getMessage(), StmtParent, TU, RegionOfInterest))) +return true; + return false; +} + bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) { switch (Na
Re: [PATCH] D20821: Fix a few issues while skipping function bodies
ogoffart updated this revision to Diff 60340. ogoffart added a comment. Using Parser::ConsumeAndStoreFunctionPrologue this time http://reviews.llvm.org/D20821 Files: lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseStmt.cpp lib/Parse/Parser.cpp lib/Sema/SemaDecl.cpp test/CodeCompletion/ctor-initializer.cpp unittests/Tooling/ToolingTest.cpp Index: unittests/Tooling/ToolingTest.cpp === --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -241,7 +241,7 @@ struct SkipBodyConsumer : public clang::ASTConsumer { /// Skip the 'skipMe' function. bool shouldSkipFunctionBody(Decl *D) override { -FunctionDecl *F = dyn_cast(D); +NamedDecl *F = dyn_cast(D); return F && F->getNameAsString() == "skipMe"; } }; @@ -255,10 +255,64 @@ }; TEST(runToolOnCode, TestSkipFunctionBody) { + std::vector Args = {"-std=c++11"}; + EXPECT_TRUE(runToolOnCode(new SkipBodyAction, "int skipMe() { an_error_here }")); EXPECT_FALSE(runToolOnCode(new SkipBodyAction, "int skipMeNot() { an_error_here }")); + + // Test constructors with initializers + EXPECT_TRUE(runToolOnCodeWithArgs( + new SkipBodyAction, + "struct skipMe { skipMe() : an_error() { more error } };", Args)); + EXPECT_TRUE(runToolOnCodeWithArgs( + new SkipBodyAction, "struct skipMe { skipMe(); };" + "skipMe::skipMe() : an_error([](){;}) { more error }", + Args)); + EXPECT_TRUE(runToolOnCodeWithArgs( + new SkipBodyAction, "struct skipMe { skipMe(); };" + "skipMe::skipMe() : an_error{[](){;}} { more error }", + Args)); + EXPECT_TRUE(runToolOnCodeWithArgs( + new SkipBodyAction, + "struct skipMe { skipMe(); };" + "skipMe::skipMe() : a(e)>>(), f{}, g() { error }", + Args)); + EXPECT_TRUE(runToolOnCodeWithArgs( + new SkipBodyAction, "struct skipMe { skipMe() : bases()... { error } };", + Args)); + + EXPECT_FALSE(runToolOnCodeWithArgs( + new SkipBodyAction, "struct skipMeNot { skipMeNot() : an_error() { } };", + Args)); + EXPECT_FALSE(runToolOnCodeWithArgs(new SkipBodyAction, + "struct skipMeNot { skipMeNot(); };" + "skipMeNot::skipMeNot() : an_error() { }", + Args)); + + // Try/catch + EXPECT_TRUE(runToolOnCode( + new SkipBodyAction, + "void skipMe() try { an_error() } catch(error) { error };")); + EXPECT_TRUE(runToolOnCode( + new SkipBodyAction, + "struct S { void skipMe() try { an_error() } catch(error) { error } };")); + EXPECT_TRUE( + runToolOnCode(new SkipBodyAction, +"void skipMe() try { an_error() } catch(error) { error; }" +"catch(error) { error } catch (error) { }")); + EXPECT_FALSE(runToolOnCode( + new SkipBodyAction, + "void skipMe() try something;")); // don't crash while parsing + + // Template + EXPECT_TRUE(runToolOnCode( + new SkipBodyAction, "template int skipMe() { an_error_here }" + "int x = skipMe();")); + EXPECT_FALSE( + runToolOnCode(new SkipBodyAction, +"template int skipMeNot() { an_error_here }")); } TEST(runToolOnCodeWithArgs, TestNoDepFile) { Index: test/CodeCompletion/ctor-initializer.cpp === --- /dev/null +++ test/CodeCompletion/ctor-initializer.cpp @@ -0,0 +1,41 @@ +struct Base1 { + Base1() : {} + // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s + // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>) + // CHECK-CC1: COMPLETION: Pattern : member2(<#args#> + + Base1(int) : member1(123), {} + // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:7:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s + // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>) + // CHECK-CC2: COMPLETION: Pattern : member2(<#args#> + + int member1; + float member2; +}; + +struct Derived : public Base1 { + Derived(); + Derived(int); + Derived(float); + int deriv1; +}; + +Derived::Derived() : {} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>) +// CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>) + +Derived::Derived(int) try : { +} catch (...) { +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:28:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>) +// CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>) + +Derived::Derived(float) try : Base1(), +{ +} catch (...) { +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:35:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s +// CHECK-CC
r272961 - Functions declared in a scope should not hide previous declaration in earlier scopes
Author: ogoffart Date: Thu Jun 16 16:39:46 2016 New Revision: 272961 URL: http://llvm.org/viewvc/llvm-project?rev=272961&view=rev Log: Functions declared in a scope should not hide previous declaration in earlier scopes This code should be an error: void foo(int); void f3() { int foo(float); { float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} } } the foo(float) function declared at function scope should not hide the float(int) while trying to redeclare functions. Differential Revision: http://reviews.llvm.org/D19763 Modified: cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/test/SemaCXX/function-redecl.cpp Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=272961&r1=272960&r2=272961&view=diff == --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Jun 16 16:39:46 2016 @@ -1078,32 +1078,35 @@ bool Sema::CppLookupName(LookupResult &R for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { DeclContext *Ctx = S->getEntity(); - +bool SearchNamespaceScope = true; // Check whether the IdResolver has anything in this scope. -bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { -if (NameKind == LookupRedeclarationWithLinkage) { +if (NameKind == LookupRedeclarationWithLinkage && +!(*I)->isTemplateParameter()) { + // If it's a template parameter, we still find it, so we can diagnose + // the invalid redeclaration. + // Determine whether this (or a previous) declaration is // out-of-scope. if (!LeftStartingScope && !Initial->isDeclScope(*I)) LeftStartingScope = true; // If we found something outside of our starting scope that - // does not have linkage, skip it. If it's a template parameter, - // we still find it, so we can diagnose the invalid redeclaration. - if (LeftStartingScope && !((*I)->hasLinkage()) && - !(*I)->isTemplateParameter()) { + // does not have linkage, skip it. + if (LeftStartingScope && !((*I)->hasLinkage())) { R.setShadowed(); continue; } +} else { + // We found something in this scope, we should not look at the + // namespace scope + SearchNamespaceScope = false; } - -Found = true; R.addDecl(ND); } } -if (Found) { +if (!SearchNamespaceScope) { R.resolveKind(); if (S->isClassScope()) if (CXXRecordDecl *Record = dyn_cast_or_null(Ctx)) Modified: cfe/trunk/test/SemaCXX/function-redecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/function-redecl.cpp?rev=272961&r1=272960&r2=272961&view=diff == --- cfe/trunk/test/SemaCXX/function-redecl.cpp (original) +++ cfe/trunk/test/SemaCXX/function-redecl.cpp Thu Jun 16 16:39:46 2016 @@ -7,7 +7,7 @@ namespace N { void bar(int); // expected-note 2{{previous declaration is here}} } - void foo(int); // expected-note 2{{previous declaration is here}} + void foo(int); // expected-note 3{{previous declaration is here}} void f2() { int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} @@ -25,6 +25,13 @@ namespace N { } } } + + void f3() { +int foo(float); +{ + float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} +} + } } class A { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D19763: Functions declared in a scope should not hide previous declaration in earlier scopes
This revision was automatically updated to reflect the committed changes. Closed by commit rL272961: Functions declared in a scope should not hide previous declaration in earlier… (authored by ogoffart). Changed prior to commit: http://reviews.llvm.org/D19763?vs=55712&id=61033#toc Repository: rL LLVM http://reviews.llvm.org/D19763 Files: cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/test/SemaCXX/function-redecl.cpp Index: cfe/trunk/test/SemaCXX/function-redecl.cpp === --- cfe/trunk/test/SemaCXX/function-redecl.cpp +++ cfe/trunk/test/SemaCXX/function-redecl.cpp @@ -7,7 +7,7 @@ void bar(int); // expected-note 2{{previous declaration is here}} } - void foo(int); // expected-note 2{{previous declaration is here}} + void foo(int); // expected-note 3{{previous declaration is here}} void f2() { int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} @@ -25,6 +25,13 @@ } } } + + void f3() { +int foo(float); +{ + float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} +} + } } class A { Index: cfe/trunk/lib/Sema/SemaLookup.cpp === --- cfe/trunk/lib/Sema/SemaLookup.cpp +++ cfe/trunk/lib/Sema/SemaLookup.cpp @@ -1078,32 +1078,35 @@ for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { DeclContext *Ctx = S->getEntity(); - +bool SearchNamespaceScope = true; // Check whether the IdResolver has anything in this scope. -bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { -if (NameKind == LookupRedeclarationWithLinkage) { +if (NameKind == LookupRedeclarationWithLinkage && +!(*I)->isTemplateParameter()) { + // If it's a template parameter, we still find it, so we can diagnose + // the invalid redeclaration. + // Determine whether this (or a previous) declaration is // out-of-scope. if (!LeftStartingScope && !Initial->isDeclScope(*I)) LeftStartingScope = true; // If we found something outside of our starting scope that - // does not have linkage, skip it. If it's a template parameter, - // we still find it, so we can diagnose the invalid redeclaration. - if (LeftStartingScope && !((*I)->hasLinkage()) && - !(*I)->isTemplateParameter()) { + // does not have linkage, skip it. + if (LeftStartingScope && !((*I)->hasLinkage())) { R.setShadowed(); continue; } +} else { + // We found something in this scope, we should not look at the + // namespace scope + SearchNamespaceScope = false; } - -Found = true; R.addDecl(ND); } } -if (Found) { +if (!SearchNamespaceScope) { R.resolveKind(); if (S->isClassScope()) if (CXXRecordDecl *Record = dyn_cast_or_null(Ctx)) Index: cfe/trunk/test/SemaCXX/function-redecl.cpp === --- cfe/trunk/test/SemaCXX/function-redecl.cpp +++ cfe/trunk/test/SemaCXX/function-redecl.cpp @@ -7,7 +7,7 @@ void bar(int); // expected-note 2{{previous declaration is here}} } - void foo(int); // expected-note 2{{previous declaration is here}} + void foo(int); // expected-note 3{{previous declaration is here}} void f2() { int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} @@ -25,6 +25,13 @@ } } } + + void f3() { +int foo(float); +{ + float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} +} + } } class A { Index: cfe/trunk/lib/Sema/SemaLookup.cpp === --- cfe/trunk/lib/Sema/SemaLookup.cpp +++ cfe/trunk/lib/Sema/SemaLookup.cpp @@ -1078,32 +1078,35 @@ for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { DeclContext *Ctx = S->getEntity(); - +bool SearchNamespaceScope = true; // Check whether the IdResolver has anything in this scope. -bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { -if (NameKind == LookupRedeclarationWithLinkage) { +if (NameKind == LookupRedeclarationWithLinkage && +!(*I)->isTemplateParameter()) { + // If it's a template parameter, we still find it, so we can diagnose + // the invalid redeclaration. + // Determine whether this (or a previous) declaration is // out-of-scope. if (!LeftStartingScope && !Initial->isDeclScope
r272962 - Keep invalid functions as part of the AST
Author: ogoffart Date: Thu Jun 16 16:39:55 2016 New Revision: 272962 URL: http://llvm.org/viewvc/llvm-project?rev=272962&view=rev Log: Keep invalid functions as part of the AST Differential Revision: http://reviews.llvm.org/D19764 Modified: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/Misc/ast-dump-invalid.cpp cfe/trunk/test/Sema/predefined-function.c Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=272962&r1=272961&r2=272962&view=diff == --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jun 16 16:39:55 2016 @@ -5100,10 +5100,9 @@ NamedDecl *Sema::HandleDeclarator(Scope if (!New) return nullptr; - // If this has an identifier and is not an invalid redeclaration or - // function template specialization, add it to the scope stack. - if (New->getDeclName() && AddToScope && - !(D.isRedeclaration() && New->isInvalidDecl())) { + // If this has an identifier and is not a function template specialization, + // add it to the scope stack. + if (New->getDeclName() && AddToScope) { // Only make a locally-scoped extern declaration visible if it is the first // declaration of this entity. Qualified lookup for such an entity should // only find this declaration if there is no visible declaration of it. Modified: cfe/trunk/test/Misc/ast-dump-invalid.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-invalid.cpp?rev=272962&r1=272961&r2=272962&view=diff == --- cfe/trunk/test/Misc/ast-dump-invalid.cpp (original) +++ cfe/trunk/test/Misc/ast-dump-invalid.cpp Thu Jun 16 16:39:55 2016 @@ -41,3 +41,24 @@ int g(int i) { // CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + +namespace TestInvalidFunctionDecl { +struct Str { + double foo1(double, invalid_type); +}; +double Str::foo1(double, invalid_type) +{ return 45; } +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl +// CHECK-NEXT: |-CXXRecordDecl {{.*}} line:46:8 struct Str definition +// CHECK-NEXT: | |-CXXRecordDecl {{.*}} col:8 implicit struct Str +// CHECK-NEXT: | `-CXXMethodDecl {{.*}} col:11 invalid foo1 'double (double, int)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} col:22 'double' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} > col:36 invalid 'int' +// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}} line:49:13 invalid foo1 'double (double, int)' +// CHECK-NEXT: |-ParmVarDecl {{.*}} col:24 'double' +// CHECK-NEXT: |-ParmVarDecl {{.*}} > col:38 invalid 'int' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 45 Modified: cfe/trunk/test/Sema/predefined-function.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/predefined-function.c?rev=272962&r1=272961&r2=272962&view=diff == --- cfe/trunk/test/Sema/predefined-function.c (original) +++ cfe/trunk/test/Sema/predefined-function.c Thu Jun 16 16:39:55 2016 @@ -4,14 +4,13 @@ char *funk(int format); enum Test {A=-1}; char *funk(enum Test x); -int eli(float b); // expected-note {{previous declaration is here}} \ -// expected-note{{passing argument to parameter 'b' here}} +int eli(float b); // expected-note {{previous declaration is here}} int b(int c) {return 1;} int foo(); int foo() { int eli(int (int)); // expected-error {{conflicting types for 'eli'}} - eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible type 'float'}} + eli(b); return 0; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r272963 - Fix a few issues while skipping function bodies
Author: ogoffart Date: Thu Jun 16 16:40:06 2016 New Revision: 272963 URL: http://llvm.org/viewvc/llvm-project?rev=272963&view=rev Log: Fix a few issues while skipping function bodies - In functions with try { } catch { }, only the try block would be skipped, not the catch blocks - The template functions would still be parsed. - The initializers within a constructor would still be parsed. - The inline functions within class would still be stored, only to be discared later. - Invalid code with try would assert (as in "int foo() try assert_here") This attempt to do even less while skipping function bodies. Differential Revision: http://reviews.llvm.org/D20821 Added: cfe/trunk/test/CodeCompletion/ctor-initializer.cpp Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp cfe/trunk/lib/Parse/ParseObjc.cpp cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/lib/Parse/Parser.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/unittests/Tooling/ToolingTest.cpp Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=272963&r1=272962&r2=272963&view=diff == --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original) +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Thu Jun 16 16:40:06 2016 @@ -101,6 +101,12 @@ NamedDecl *Parser::ParseCXXInlineMethodD return FnD; } + if (SkipFunctionBodies && (!FnD || Actions.canSkipFunctionBody(FnD)) && + trySkippingFunctionBody()) { +Actions.ActOnSkippedFunctionBody(FnD); +return FnD; + } + // In delayed template parsing mode, if we are within a class template // or if we are about to parse function member template then consume // the tokens and store them for parsing at the end of the translation unit. Modified: cfe/trunk/lib/Parse/ParseObjc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=272963&r1=272962&r2=272963&view=diff == --- cfe/trunk/lib/Parse/ParseObjc.cpp (original) +++ cfe/trunk/lib/Parse/ParseObjc.cpp Thu Jun 16 16:40:06 2016 @@ -2656,6 +2656,12 @@ Parser::ParseObjCAutoreleasePoolStmt(Sou /// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them /// for later parsing. void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) { + if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) && + trySkippingFunctionBody()) { +Actions.ActOnSkippedFunctionBody(MDecl); +return; + } + LexedMethod* LM = new LexedMethod(this, MDecl); CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM); CachedTokens &Toks = LM->Toks; Modified: cfe/trunk/lib/Parse/ParseStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=272963&r1=272962&r2=272963&view=diff == --- cfe/trunk/lib/Parse/ParseStmt.cpp (original) +++ cfe/trunk/lib/Parse/ParseStmt.cpp Thu Jun 16 16:40:06 2016 @@ -1916,12 +1916,6 @@ Decl *Parser::ParseFunctionStatementBody assert(Tok.is(tok::l_brace)); SourceLocation LBraceLoc = Tok.getLocation(); - if (SkipFunctionBodies && (!Decl || Actions.canSkipFunctionBody(Decl)) && - trySkippingFunctionBody()) { -BodyScope.Exit(); -return Actions.ActOnSkippedFunctionBody(Decl); - } - PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, "parsing function body"); @@ -1964,12 +1958,6 @@ Decl *Parser::ParseFunctionTryBlock(Decl else Actions.ActOnDefaultCtorInitializers(Decl); - if (SkipFunctionBodies && Actions.canSkipFunctionBody(Decl) && - trySkippingFunctionBody()) { -BodyScope.Exit(); -return Actions.ActOnSkippedFunctionBody(Decl); - } - // Save and reset current vtordisp stack if we have entered a C++ method body. bool IsCXXMethod = getLangOpts().CPlusPlus && Decl && isa(Decl); @@ -1990,27 +1978,43 @@ Decl *Parser::ParseFunctionTryBlock(Decl } bool Parser::trySkippingFunctionBody() { - assert(Tok.is(tok::l_brace)); assert(SkipFunctionBodies && "Should only be called when SkipFunctionBodies is enabled"); - if (!PP.isCodeCompletionEnabled()) { -ConsumeBrace(); -SkipUntil(tok::r_brace); +SkipFunctionBody(); return true; } // We're in code-completion mode. Skip parsing for all function bodies unless // the body contains the code-completion point. TentativeParsingAction PA(*this); - ConsumeBrace(); - if (SkipUntil(tok::r_brace, StopAtCodeCompletion)) { + bool IsTryCatch = Tok.is(tok::kw_try); + CachedTokens Toks; + bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks); + if (llvm::any_of(Toks, [](const Token &Tok) { +return Tok.is(tok::code_completion); + })) { +PA.Revert(); +return
Re: [PATCH] D20821: Fix a few issues while skipping function bodies
This revision was automatically updated to reflect the committed changes. Closed by commit rL272963: Fix a few issues while skipping function bodies (authored by ogoffart). Changed prior to commit: http://reviews.llvm.org/D20821?vs=60340&id=61035#toc Repository: rL LLVM http://reviews.llvm.org/D20821 Files: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp cfe/trunk/lib/Parse/ParseObjc.cpp cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/lib/Parse/Parser.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/CodeCompletion/ctor-initializer.cpp cfe/trunk/unittests/Tooling/ToolingTest.cpp Index: cfe/trunk/test/CodeCompletion/ctor-initializer.cpp === --- cfe/trunk/test/CodeCompletion/ctor-initializer.cpp +++ cfe/trunk/test/CodeCompletion/ctor-initializer.cpp @@ -0,0 +1,41 @@ +struct Base1 { + Base1() : {} + // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s + // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>) + // CHECK-CC1: COMPLETION: Pattern : member2(<#args#> + + Base1(int) : member1(123), {} + // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:7:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s + // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>) + // CHECK-CC2: COMPLETION: Pattern : member2(<#args#> + + int member1; + float member2; +}; + +struct Derived : public Base1 { + Derived(); + Derived(int); + Derived(float); + int deriv1; +}; + +Derived::Derived() : {} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>) +// CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>) + +Derived::Derived(int) try : { +} catch (...) { +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:28:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>) +// CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>) + +Derived::Derived(float) try : Base1(), +{ +} catch (...) { +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:35:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s +// CHECK-CC5-NOT: COMPLETION: Pattern : Base1(<#args#>) +// CHECK-CC5: COMPLETION: Pattern : deriv1(<#args#>) Index: cfe/trunk/lib/Sema/SemaDecl.cpp === --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -11384,7 +11384,7 @@ FD->setHasSkippedBody(); else if (ObjCMethodDecl *MD = dyn_cast_or_null(Decl)) MD->setHasSkippedBody(); - return ActOnFinishFunctionBody(Decl, nullptr); + return Decl; } Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { Index: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp === --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp @@ -101,6 +101,12 @@ return FnD; } + if (SkipFunctionBodies && (!FnD || Actions.canSkipFunctionBody(FnD)) && + trySkippingFunctionBody()) { +Actions.ActOnSkippedFunctionBody(FnD); +return FnD; + } + // In delayed template parsing mode, if we are within a class template // or if we are about to parse function member template then consume // the tokens and store them for parsing at the end of the translation unit. Index: cfe/trunk/lib/Parse/ParseObjc.cpp === --- cfe/trunk/lib/Parse/ParseObjc.cpp +++ cfe/trunk/lib/Parse/ParseObjc.cpp @@ -2656,6 +2656,12 @@ /// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them /// for later parsing. void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) { + if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) && + trySkippingFunctionBody()) { +Actions.ActOnSkippedFunctionBody(MDecl); +return; + } + LexedMethod* LM = new LexedMethod(this, MDecl); CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM); CachedTokens &Toks = LM->Toks; Index: cfe/trunk/lib/Parse/Parser.cpp === --- cfe/trunk/lib/Parse/Parser.cpp +++ cfe/trunk/lib/Parse/Parser.cpp @@ -1044,6 +1044,12 @@ D.complete(DP); D.getMutableDeclSpec().abort(); +if (SkipFunctionBodies && (!DP || Actions.canSkipFunctionBody(DP)) && +trySkippingFunctionBody()) { + BodyScope.Exit(); + return Actions.ActOnSkippedFunctionBody(DP); +} + CachedTokens Toks; LexTemplateFunctionForLateParsing(Toks); @@ -1136,6 +1142,13 @@ return Res; } + if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) && + trySkippingFunctionBody()) { +BodyScope.Exit(); +Actions.ActOnSkippedFunctionBody(Res); +return Actions.ActOnFinishFunctionBody(Res, nullptr, false); + } + if (Tok.is(tok::kw_tr
Re: [PATCH] D19764: Keep invalid functions as part of the AST
This revision was automatically updated to reflect the committed changes. Closed by commit rL272962: Keep invalid functions as part of the AST (authored by ogoffart). Changed prior to commit: http://reviews.llvm.org/D19764?vs=55714&id=61034#toc Repository: rL LLVM http://reviews.llvm.org/D19764 Files: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/Misc/ast-dump-invalid.cpp cfe/trunk/test/Sema/predefined-function.c Index: cfe/trunk/test/Sema/predefined-function.c === --- cfe/trunk/test/Sema/predefined-function.c +++ cfe/trunk/test/Sema/predefined-function.c @@ -4,14 +4,13 @@ enum Test {A=-1}; char *funk(enum Test x); -int eli(float b); // expected-note {{previous declaration is here}} \ -// expected-note{{passing argument to parameter 'b' here}} +int eli(float b); // expected-note {{previous declaration is here}} int b(int c) {return 1;} int foo(); int foo() { int eli(int (int)); // expected-error {{conflicting types for 'eli'}} - eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible type 'float'}} + eli(b); return 0; } Index: cfe/trunk/test/Misc/ast-dump-invalid.cpp === --- cfe/trunk/test/Misc/ast-dump-invalid.cpp +++ cfe/trunk/test/Misc/ast-dump-invalid.cpp @@ -41,3 +41,24 @@ // CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + +namespace TestInvalidFunctionDecl { +struct Str { + double foo1(double, invalid_type); +}; +double Str::foo1(double, invalid_type) +{ return 45; } +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl +// CHECK-NEXT: |-CXXRecordDecl {{.*}} line:46:8 struct Str definition +// CHECK-NEXT: | |-CXXRecordDecl {{.*}} col:8 implicit struct Str +// CHECK-NEXT: | `-CXXMethodDecl {{.*}} col:11 invalid foo1 'double (double, int)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} col:22 'double' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} > col:36 invalid 'int' +// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}} line:49:13 invalid foo1 'double (double, int)' +// CHECK-NEXT: |-ParmVarDecl {{.*}} col:24 'double' +// CHECK-NEXT: |-ParmVarDecl {{.*}} > col:38 invalid 'int' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 45 Index: cfe/trunk/lib/Sema/SemaDecl.cpp === --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -5100,10 +5100,9 @@ if (!New) return nullptr; - // If this has an identifier and is not an invalid redeclaration or - // function template specialization, add it to the scope stack. - if (New->getDeclName() && AddToScope && - !(D.isRedeclaration() && New->isInvalidDecl())) { + // If this has an identifier and is not a function template specialization, + // add it to the scope stack. + if (New->getDeclName() && AddToScope) { // Only make a locally-scoped extern declaration visible if it is the first // declaration of this entity. Qualified lookup for such an entity should // only find this declaration if there is no visible declaration of it. Index: cfe/trunk/test/Sema/predefined-function.c === --- cfe/trunk/test/Sema/predefined-function.c +++ cfe/trunk/test/Sema/predefined-function.c @@ -4,14 +4,13 @@ enum Test {A=-1}; char *funk(enum Test x); -int eli(float b); // expected-note {{previous declaration is here}} \ -// expected-note{{passing argument to parameter 'b' here}} +int eli(float b); // expected-note {{previous declaration is here}} int b(int c) {return 1;} int foo(); int foo() { int eli(int (int)); // expected-error {{conflicting types for 'eli'}} - eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible type 'float'}} + eli(b); return 0; } Index: cfe/trunk/test/Misc/ast-dump-invalid.cpp === --- cfe/trunk/test/Misc/ast-dump-invalid.cpp +++ cfe/trunk/test/Misc/ast-dump-invalid.cpp @@ -41,3 +41,24 @@ // CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + +namespace TestInvalidFunctionDecl { +struct Str { + double foo1(double, invalid_type); +}; +double Str::foo1(double, invalid_type) +{ return 45; } +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl +// CHECK-NEXT: |-CXXRecordDecl {{.*}} line:46:8 struct Str definition +// CHECK-NEXT: | |-CXXRecordDecl {{.*}} col:8 implicit struct Str +// CHECK-NEXT: | `-CXXMethodDecl {{.*}} col:11 invalid foo1 'double (double, int)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} col:22 'do
Re: [PATCH] D19327: Keep invalid function body as part of the AST
ogoffart abandoned this revision. ogoffart added a comment. Replaced by http://reviews.llvm.org/D19764 http://reviews.llvm.org/D19327 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21497: Fix test to specify C++03 (fails with C++11).
ogoffart added a comment. I'm sorry for commiting broken test. However this is supposed to work also in C++11 mode. I'm investigating what's wrong. http://reviews.llvm.org/D21497 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21497: Fix test to specify C++03 (fails with C++11).
ogoffart added a comment. I made http://reviews.llvm.org/D21502 that should also fix this test. http://reviews.llvm.org/D21497 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11
ogoffart added a comment. Ping. The problem i'm fixing here is how we recover invalid code in the ctor-init part as we skip the function body. In particular, we want to know if the '{' is the begining of the body or not. In C++03, we always consider it as the beginng of the body. The problem was that in C++11 we don't, making the code skip too much, causing worse parse error later. So what this patch is doing is finding heuristics to know if the '{' is starting a function body or not. The rules are the following: If we are not in a template argument, anf that the previous tokens are not an identifier, or a > , then it is much more likely to be the function body. We verify that further by checking that the token after the matching '}' I also changed the code to just ignore the code_completion token at this point. The previous code was making it thinking that it would then be a template argument. But this is not likely. http://reviews.llvm.org/D21502 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r263639 - Fix destructor definition of invalid classes
Author: ogoffart Date: Wed Mar 16 09:36:11 2016 New Revision: 263639 URL: http://llvm.org/viewvc/llvm-project?rev=263639&view=rev Log: Fix destructor definition of invalid classes The declaration of the destructor of an invalid class was not properly marked as noexcept. As a result, the definition of the same destructor, which was properly implicitly marked as noexcept, would not match the definition. This would cause the definition CXXDestructorDecl to be matked as invalid and omited from the AST. Differential Revision: http://reviews.llvm.org/D17988 Modified: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/SemaCXX/destructor.cpp Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=263639&r1=263638&r2=263639&view=diff == --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Mar 16 09:36:11 2016 @@ -13862,15 +13862,17 @@ void Sema::ActOnFields(Scope *S, SourceL I = CXXRecord->conversion_begin(), E = CXXRecord->conversion_end(); I != E; ++I) I.setAccess((*I)->getAccess()); - -if (!CXXRecord->isDependentType()) { - if (CXXRecord->hasUserDeclaredDestructor()) { -// Adjust user-defined destructor exception spec. -if (getLangOpts().CPlusPlus11) - AdjustDestructorExceptionSpec(CXXRecord, -CXXRecord->getDestructor()); - } + } + if (!CXXRecord->isDependentType()) { +if (CXXRecord->hasUserDeclaredDestructor()) { + // Adjust user-defined destructor exception spec. + if (getLangOpts().CPlusPlus11) +AdjustDestructorExceptionSpec(CXXRecord, + CXXRecord->getDestructor()); +} + +if (!CXXRecord->isInvalidDecl()) { // Add any implicitly-declared members to this class. AddImplicitlyDeclaredMembersToClass(CXXRecord); Modified: cfe/trunk/test/SemaCXX/destructor.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=263639&r1=263638&r2=263639&view=diff == --- cfe/trunk/test/SemaCXX/destructor.cpp (original) +++ cfe/trunk/test/SemaCXX/destructor.cpp Wed Mar 16 09:36:11 2016 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s // RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s class A { public: @@ -423,3 +423,11 @@ void g(S s) { (s.~S); // expected-error{{reference to destructor must be called}} } } + +class Invalid { +~Invalid(); +UnknownType xx; // expected-error{{unknown type name}} +}; + +// The constructor definition should not have errors +Invalid::~Invalid() {} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D17988: Fix destructor definition of invalid classes
This revision was automatically updated to reflect the committed changes. Closed by commit rL263639: Fix destructor definition of invalid classes (authored by ogoffart). Changed prior to commit: http://reviews.llvm.org/D17988?vs=50124&id=50822#toc Repository: rL LLVM http://reviews.llvm.org/D17988 Files: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/SemaCXX/destructor.cpp Index: cfe/trunk/test/SemaCXX/destructor.cpp === --- cfe/trunk/test/SemaCXX/destructor.cpp +++ cfe/trunk/test/SemaCXX/destructor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s // RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s class A { public: @@ -423,3 +423,11 @@ (s.~S); // expected-error{{reference to destructor must be called}} } } + +class Invalid { +~Invalid(); +UnknownType xx; // expected-error{{unknown type name}} +}; + +// The constructor definition should not have errors +Invalid::~Invalid() {} Index: cfe/trunk/lib/Sema/SemaDecl.cpp === --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -13862,15 +13862,17 @@ I = CXXRecord->conversion_begin(), E = CXXRecord->conversion_end(); I != E; ++I) I.setAccess((*I)->getAccess()); - -if (!CXXRecord->isDependentType()) { - if (CXXRecord->hasUserDeclaredDestructor()) { -// Adjust user-defined destructor exception spec. -if (getLangOpts().CPlusPlus11) - AdjustDestructorExceptionSpec(CXXRecord, -CXXRecord->getDestructor()); - } + } + + if (!CXXRecord->isDependentType()) { +if (CXXRecord->hasUserDeclaredDestructor()) { + // Adjust user-defined destructor exception spec. + if (getLangOpts().CPlusPlus11) +AdjustDestructorExceptionSpec(CXXRecord, + CXXRecord->getDestructor()); +} +if (!CXXRecord->isInvalidDecl()) { // Add any implicitly-declared members to this class. AddImplicitlyDeclaredMembersToClass(CXXRecord); Index: cfe/trunk/test/SemaCXX/destructor.cpp === --- cfe/trunk/test/SemaCXX/destructor.cpp +++ cfe/trunk/test/SemaCXX/destructor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s // RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s class A { public: @@ -423,3 +423,11 @@ (s.~S); // expected-error{{reference to destructor must be called}} } } + +class Invalid { +~Invalid(); +UnknownType xx; // expected-error{{unknown type name}} +}; + +// The constructor definition should not have errors +Invalid::~Invalid() {} Index: cfe/trunk/lib/Sema/SemaDecl.cpp === --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -13862,15 +13862,17 @@ I = CXXRecord->conversion_begin(), E = CXXRecord->conversion_end(); I != E; ++I) I.setAccess((*I)->getAccess()); - -if (!CXXRecord->isDependentType()) { - if (CXXRecord->hasUserDeclaredDestructor()) { -// Adjust user-defined destructor exception spec. -if (getLangOpts().CPlusPlus11) - AdjustDestructorExceptionSpec(CXXRecord, -CXXRecord->getDestructor()); - } + } + + if (!CXXRecord->isDependentType()) { +if (CXXRecord->hasUserDeclaredDestructor()) { + // Adjust user-defined destructor exception spec. + if (getLangOpts().CPlusPlus11) +AdjustDestructorExceptionSpec(CXXRecord, + CXXRecord->getDestructor()); +} +if (!CXXRecord->isInvalidDecl()) { // Add any implicitly-declared members to this class. AddImplicitlyDeclaredMembersToClass(CXXRecord); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits