[PATCH] D48159: [clangd] Implement hover for "auto" and "decltype"
malaperle created this revision. Herald added subscribers: cfe-commits, jkorous, MaskRay, ioeric, ilya-biryukov. This allows hovering on keywords that refer to deduced types. This should cover most useful cases. Not covered: - auto template parameters: Since this can be instantiated with many types, it would not be practical to show the types. - Structured binding: This could be done later to show multiple deduced types in the hover. - auto:: (part of concepts): Outside the scope of this patch. Signed-off-by: Marc-Andre Laperle Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D48159 Files: clangd/XRefs.cpp unittests/clangd/TestTU.cpp unittests/clangd/TestTU.h unittests/clangd/XRefsTests.cpp Index: unittests/clangd/XRefsTests.cpp === --- unittests/clangd/XRefsTests.cpp +++ unittests/clangd/XRefsTests.cpp @@ -343,6 +343,13 @@ OneTest Tests[] = { { + R"cpp(// No hover +^int main() { +} + )cpp", + "", + }, + { R"cpp(// Local variable int main() { int bonjour; @@ -637,16 +644,273 @@ )cpp", "", }, + { + R"cpp(// Simple initialization with auto +void foo() { + ^auto i = 1; +} + )cpp", + "int", + }, + { + R"cpp(// Simple initialization with const auto +void foo() { + const ^auto i = 1; +} + )cpp", + "int", + }, + { + R"cpp(// Simple initialization with const auto& +void foo() { + const ^auto& i = 1; +} + )cpp", + "int", + }, + { + R"cpp(// Simple initialization with auto& +void foo() { + ^auto& i = 1; +} + )cpp", + "int", + }, + { + R"cpp(// Auto with initializer list. +namespace std +{ + template + class initializer_list {}; +} +void foo() { + ^auto i = {1,2}; +} + )cpp", + "class std::initializer_list", + }, + { + R"cpp(// User defined conversion to auto +struct Bar { + operator ^auto() const { return 10; } +}; + )cpp", + "int", + }, + { + R"cpp(// Simple initialization with decltype(auto) +void foo() { + ^decltype(auto) i = 1; +} + )cpp", + "int", + }, + { + R"cpp(// Simple initialization with const decltype(auto) +void foo() { + const int j = 0; + ^decltype(auto) i = j; +} + )cpp", + "const int", + }, + { + R"cpp(// Simple initialization with const& decltype(auto) +void foo() { + int k = 0; + const int& j = k; + ^decltype(auto) i = j; +} + )cpp", + "const int &", + }, + { + R"cpp(// Simple initialization with & decltype(auto) +void foo() { + int k = 0; + int& j = k; + ^decltype(auto) i = j; +} + )cpp", + "int &", + }, + { + R"cpp(// decltype with initializer list: nothing +namespace std +{ + template + class initializer_list {}; +} +void foo() { + ^decltype(auto) i = {1,2}; +} + )cpp", + "", + }, + { + R"cpp(// auto function return with trailing type +struct Bar {}; +^auto test() -> decltype(Bar()) { + return Bar(); +} + )cpp", + "struct Bar", + }, + { + R"cpp(// trailing return type +struct Bar {}; +auto test() -> ^decltype(Bar()) { + return Bar(); +} + )cpp", + "struct Bar", + }, + { + R"cpp(// auto in function return +struct Bar {}; +^auto test() { + return Bar(); +} + )cpp", + "struct Bar", + }, + { + R"cpp(// auto& in function return +struct Bar {}; +^auto& test() { + return Bar(); +} + )cpp", + "struct Bar", + }, + { + R"cpp(// const auto& in function return +struct Bar {}; +const ^auto& test() { + return Bar(); +} + )cpp", + "struct Bar", + }, + { + R"cpp(// decltype(auto) in function return +struct Bar {}; +^decltype(auto)
[PATCH] D48027: [analyzer] Improve `CallDescription` to handle c++ method.
MTC added inline comments. Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:32 check::PostCall> { - CallDescription CStrFn; + const llvm::SmallVector CStrFnFamily = { +{"std::basic_string::c_str"}, {"std::basic_string::c_str"}, NoQ wrote: > xazax.hun wrote: > > I am not sure if this is the right solution in case of this check. We > > should track `c_str` calls regardless of what the template parameter is, so > > supporting any instantiation of `basic_string` is desired. This might not > > be the case, however, for other checks. > > > > If we think it is more likely we do not care about the template arguments, > > maybe a separate API could be used, where we pass the qualified name of the > > class separately without the template arguments. > > Alternatively, we could use matches name so the users could use regexps. > > > > At this point I also wonder what isCalled API gives us compared to > > matchers? Maybe it is more convenient to use than calling a `match`. Also, > > isCalled API has an IdentifierInfo cached which could be used for > > relatively efficient checks. > > > > @NoQ what do you think? > > > > > I agree that it's better to match the chain of classes and namespaces (in as > much detail as the user cares to provide) and discard template parameters. > > For example, i wish that a `CallDescription` that's defined as `{"std", > "basic_string", "c_str"}` would be able to match both `std::string::c_str()` > and `std::__1::string::c_str()`. Yea, checker writers may can't provide all the template arguments, and it's not convenient to use! I will try to give a better solution! Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:65 auto *TypeDecl = TypedR->getValueType()->getAsCXXRecordDecl(); if (TypeDecl->getName() != "basic_string") return; xazax.hun wrote: > If we check for fully qualified names, this check might be redundant. Right, thanks! Comment at: lib/StaticAnalyzer/Core/CallEvent.cpp:273 + auto Matches = + match(namedDecl(hasName(CD.FuncName)).bind("match_qualified_name"), *ND, +LCtx->getAnalysisDeclContext()->getASTContext()); xazax.hun wrote: > Doesn't match also traverse the subtree of the AST? We only need to check if > that particular node matches the qualified name. I wonder if we could, during > the traversal, find another node that is a match unintentionally. Yea, this maybe a problem, I will test whether this is going to happen and give a fine-grained match. Thanks! Repository: rC Clang https://reviews.llvm.org/D48027 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47687: [Sema] Missing -Wlogical-op-parentheses warnings in macros (PR18971)
Higuoxing updated this revision to Diff 151290. Higuoxing added a comment. Ping, well, I think I understand `@dexonsmith`'s idea. `Actionable` macro argument is just like something like this #define foo(x) ( (void)(x) ) when we using it by foo(a && b || c); we could add parentheses for it by foo((a && b) || c); However, the following example is `not actionable` #define foo(op0, op1, x, y, z) ( (void)(x op0 y op1 z) ) when we using it by foo(&&, ||, x, y, z); because, we also probably use it by foo(+, *, x, y, z) So, we cannot add parentheses for it carelessly... My opinion is that, to judge if an `expr` is actionable is to test if the op and both LHS and RHS are from same context or same argument position from macro... But I cannot find such API for indicating a `expression` expanded position exactly. There are API like: `isMacroArgExpansion` and `isMacroBodyExpansion` which is determined by row string positions... So, what I can do now for this is that using API `isMacroArgExpansion()` to let it check the parentheses defined or expanded totally inside a macro like #define foo(x, y, z) ( x && y || z ) The shortage is that we cannot check parentheses for this case: foo(x && y || z); because the operator is expanded from macro arguments. Thanks https://reviews.llvm.org/D47687 Files: lib/Sema/SemaExpr.cpp test/Sema/logical-op-parentheses-in-macros.c Index: test/Sema/logical-op-parentheses-in-macros.c === --- test/Sema/logical-op-parentheses-in-macros.c +++ test/Sema/logical-op-parentheses-in-macros.c @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -Wparentheses -fsyntax-only -verify=logical_op_parentheses_check %s + +// operator of this case is expanded from macro function argument +#define macro_op_parentheses_check(x) ( \ + ( (void)(x) ) \ +) + +// operator of this case is expanded from macro function body +#define macro_op_parentheses_check_ops_args(op0, op1, x, y, z) ( \ + ( (void) (x op0 y op1 z ) ) \ +) + +// operator of this case is expanded from macro function body +#define macro_op_parentheses_check_ops_args2(op0, op1, op2, w, x, y, z) ( \ + ( (void) (w op0 x op1 y op2 z) ) \ +) + +// operator of this case is expanded from marco body +#define macro_op_parentheses_check_ops_body(x, y, z) ( \ + ( (void) (x && y || z) ) \ +) + +void logical_op_from_macro_arguments(unsigned i) { + macro_op_parentheses_check(i || i && i); // no warning. + macro_op_parentheses_check(i || i && "I love LLVM"); // no warning. + macro_op_parentheses_check("I love LLVM" && i || i); // no warning. + + macro_op_parentheses_check(i || i && "I love LLVM" || i); // no warning. + macro_op_parentheses_check(i || "I love LLVM" && i || i); // no warning. + macro_op_parentheses_check(i && i || 0); // no warning. + macro_op_parentheses_check(0 || i && i); // no warning. +} + +void logical_op_from_macro_arguments2(unsigned i) { + macro_op_parentheses_check_ops_args(||, &&, i, i, i); // no warning. + macro_op_parentheses_check_ops_args(||, &&, i, i, "I love LLVM"); // no warning. + macro_op_parentheses_check_ops_args(&&, ||, "I love LLVM", i, i); // no warning. + + macro_op_parentheses_check_ops_args2(||, &&, ||, i, i, "I love LLVM", i); // no warning. + macro_op_parentheses_check_ops_args2(||, &&, ||, i, "I love LLVM", i, i); // no warning. + + macro_op_parentheses_check_ops_args(&&, ||, i, i, 0); // no warning. + macro_op_parentheses_check_ops_args(||, &&, 0, i, i); // no warning. +} + +void logical_op_from_macro_body(unsigned i) { + macro_op_parentheses_check_ops_body(i, i, i); // logical_op_parentheses_check-warning {{'&&' within '||'}} \ +// logical_op_parentheses_check-note {{place parentheses around the '&&' expression to silence this warning}} +} \ No newline at end of file Index: lib/Sema/SemaExpr.cpp === --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -12172,7 +12172,7 @@ EmitDiagnosticForLogicalAndInLogicalOr(Sema , SourceLocation OpLoc, BinaryOperator *Bop) { assert(Bop->getOpcode() == BO_LAnd); - Self.Diag(Bop->getOperatorLoc(), diag::warn_logical_and_in_logical_or) + Self.Diag(Bop->getOperatorLoc(), diag::warn_logical_and_in_logical_or) << Bop->getSourceRange() << OpLoc; SuggestParentheses(Self, Bop->getOperatorLoc(), Self.PDiag(diag::note_precedence_silence) @@ -12205,6 +12205,7 @@ if (EvaluatesAsFalse(S, RHSExpr)) return; // If it's "1 && a || b" don't warn since the precedence doesn't matter. + // And 'assert("some message" && a || b)' don't warn as well. if (!EvaluatesAsTrue(S, Bop->getLHS())) return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop); } else if (Bop->getOpcode() == BO_LOr) { @@ -12227,6 +12228,7 @@ if (EvaluatesAsFalse(S, LHSExpr))
[PATCH] D47405: [analyzer] Re-enable C++17-specific return value constructors.
This revision was automatically updated to reflect the committed changes. Closed by commit rC334684: [analyzer] Re-enable C++17-specific RVO construction contexts. (authored by dergachev, committed by ). Herald added a subscriber: mikhail.ramalho. Repository: rC Clang https://reviews.llvm.org/D47405 Files: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp test/Analysis/cxx17-mandatory-elision.cpp Index: test/Analysis/cxx17-mandatory-elision.cpp === --- test/Analysis/cxx17-mandatory-elision.cpp +++ test/Analysis/cxx17-mandatory-elision.cpp @@ -150,9 +150,8 @@ ClassWithoutDestructor c = make3(v); #if __cplusplus >= 201703L - // FIXME: Both should be TRUE. clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} - clang_analyzer_eval(v.buf[0] == ); // expected-warning{{FALSE}} + clang_analyzer_eval(v.buf[0] == ); // expected-warning{{TRUE}} #else clang_analyzer_eval(v.len == 5); // expected-warning{{TRUE}} clang_analyzer_eval(v.buf[0] != v.buf[1]); // expected-warning{{TRUE}} @@ -183,6 +182,13 @@ AddressVector v; { ClassWithDestructor c = ClassWithDestructor(v); +// Check if the last destructor is an automatic destructor. +// A temporary destructor would have fired by now. +#if __cplusplus >= 201703L +clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} +#else +clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}} +#endif } #if __cplusplus >= 201703L // 0. Construct the variable. @@ -210,6 +216,13 @@ AddressVector v; { TestCtorInitializer t(v); +// Check if the last destructor is an automatic destructor. +// A temporary destructor would have fired by now. +#if __cplusplus >= 201703L +clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} +#else +clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}} +#endif } #if __cplusplus >= 201703L // 0. Construct the member variable. @@ -227,4 +240,53 @@ #endif } + +ClassWithDestructor make1(AddressVector ) { + return ClassWithDestructor(v); +} +ClassWithDestructor make2(AddressVector ) { + return make1(v); +} +ClassWithDestructor make3(AddressVector ) { + return make2(v); +} + +void testMultipleReturnsWithDestructors() { + AddressVector v; + { +ClassWithDestructor c = make3(v); +// Check if the last destructor is an automatic destructor. +// A temporary destructor would have fired by now. +#if __cplusplus >= 201703L +clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} +#else +clang_analyzer_eval(v.len == 9); // expected-warning{{TRUE}} +#endif + } + +#if __cplusplus >= 201703L + // 0. Construct the variable. Yes, constructor in make1() constructs + //the variable 'c'. + // 1. Destroy the variable. + clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}} +#else + // 0. Construct the temporary in make1(). + // 1. Construct the temporary in make2(). + // 2. Destroy the temporary in make1(). + // 3. Construct the temporary in make3(). + // 4. Destroy the temporary in make2(). + // 5. Construct the temporary here. + // 6. Destroy the temporary in make3(). + // 7. Construct the variable. + // 8. Destroy the temporary here. + // 9. Destroy the variable. + clang_analyzer_eval(v.len == 10); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[1] == v.buf[4]); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[3] == v.buf[6]); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[5] == v.buf[8]); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[7] == v.buf[9]); // expected-warning{{TRUE}} +#endif +} } // namespace address_vector_tests Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp === --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -180,7 +180,8 @@ } break; } -case ConstructionContext::SimpleReturnedValueKind: { +case ConstructionContext::SimpleReturnedValueKind: +case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { // The temporary is to be managed by the parent stack frame. // So build it in the parent stack frame if we're not in the // top frame of the analysis. @@ -193,16 +194,10 @@ // call in the parent stack frame. This is equivalent to not being // able to find construction context at all. break; -} else if (!isa( - RTC->getConstructionContext())) { - // FIXME: The return value is constructed directly into a - // non-temporary due to C++17 mandatory copy elision. This is not - // implemented yet. - assert(getContext().getLangOpts().CPlusPlus17); - break; } -CC =
r334684 - [analyzer] Re-enable C++17-specific RVO construction contexts.
Author: dergachev Date: Wed Jun 13 18:59:35 2018 New Revision: 334684 URL: http://llvm.org/viewvc/llvm-project?rev=334684=rev Log: [analyzer] Re-enable C++17-specific RVO construction contexts. Not contexts themselves, but rather support for them in the analyzer. Such construction contexts appear when C++17 mandatory copy elision occurs while returning an object from a function, and presence of a destructor causes a CXXBindTemporaryExpr to appear in the AST. Additionally, such construction contexts may be chained, because a return-value construction context doesn't really explain where the object is being returned into, but only points to the parent stack frame, where the object may be consumed by literally anything including another return statement. This behavior is now modeled correctly by the analyzer as long as the object is not returned beyond the boundaries of the analysis. Differential Revision: https://reviews.llvm.org/D47405 Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=334684=334683=334684=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Wed Jun 13 18:59:35 2018 @@ -180,7 +180,8 @@ std::pair ExprEng } break; } -case ConstructionContext::SimpleReturnedValueKind: { +case ConstructionContext::SimpleReturnedValueKind: +case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { // The temporary is to be managed by the parent stack frame. // So build it in the parent stack frame if we're not in the // top frame of the analysis. @@ -193,16 +194,10 @@ std::pair ExprEng // call in the parent stack frame. This is equivalent to not being // able to find construction context at all. break; -} else if (!isa( - RTC->getConstructionContext())) { - // FIXME: The return value is constructed directly into a - // non-temporary due to C++17 mandatory copy elision. This is not - // implemented yet. - assert(getContext().getLangOpts().CPlusPlus17); - break; } -CC = RTC->getConstructionContext(); -LCtx = CallerLCtx; +return prepareForObjectConstruction( +cast(SFC->getCallSite()), State, CallerLCtx, +RTC->getConstructionContext(), CallOpts); } else { // We are on the top frame of the analysis. // TODO: What exactly happens when we are? Does the temporary object @@ -212,9 +207,7 @@ std::pair ExprEng SVal V = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); return std::make_pair(State, V); } - - // Continue as if we have a temporary with a different location context. - // FALLTHROUGH. + llvm_unreachable("Unhandled return value construction context!"); } case ConstructionContext::TemporaryObjectKind: { const auto *TCC = cast(CC); @@ -261,9 +254,6 @@ std::pair ExprEng CallOpts.IsTemporaryCtorOrDtor = true; return std::make_pair(State, V); } -case ConstructionContext::CXX17ElidedCopyReturnedValueKind: - // Not implemented yet. - break; } } // If we couldn't find an existing region to construct into, assume we're Modified: cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp?rev=334684=334683=334684=diff == --- cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp (original) +++ cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp Wed Jun 13 18:59:35 2018 @@ -150,9 +150,8 @@ void testMultipleReturns() { ClassWithoutDestructor c = make3(v); #if __cplusplus >= 201703L - // FIXME: Both should be TRUE. clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} - clang_analyzer_eval(v.buf[0] == ); // expected-warning{{FALSE}} + clang_analyzer_eval(v.buf[0] == ); // expected-warning{{TRUE}} #else clang_analyzer_eval(v.len == 5); // expected-warning{{TRUE}} clang_analyzer_eval(v.buf[0] != v.buf[1]); // expected-warning{{TRUE}} @@ -183,6 +182,13 @@ void testVariable() { AddressVector v; { ClassWithDestructor c = ClassWithDestructor(v); +// Check if the last destructor is an automatic destructor. +// A temporary destructor would have fired by now. +#if __cplusplus >= 201703L +clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} +#else +clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}} +#endif } #if __cplusplus >= 201703L // 0. Construct the variable. @@
[PATCH] D47351: [analyzer] Re-enable C++17-specific variable and member variable construction contexts.
This revision was automatically updated to reflect the committed changes. Closed by commit rC334683: [analyzer] Re-enable C++17-specific variable and member construction contexts. (authored by dergachev, committed by ). Herald added a subscriber: mikhail.ramalho. Repository: rC Clang https://reviews.llvm.org/D47351 Files: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp test/Analysis/cxx17-mandatory-elision.cpp Index: test/Analysis/cxx17-mandatory-elision.cpp === --- test/Analysis/cxx17-mandatory-elision.cpp +++ test/Analysis/cxx17-mandatory-elision.cpp @@ -49,9 +49,64 @@ } }; + +struct A { + int x; + A(): x(0) {} + ~A() {} +}; + +struct B { + A a; + B() : a(A()) {} +}; + +void foo() { + B b; + clang_analyzer_eval(b.a.x == 0); // expected-warning{{TRUE}} +} + } // namespace ctor_initializer +namespace elision_on_ternary_op_branches { +class C1 { + int x; +public: + C1(int x): x(x) {} + int getX() const { return x; } + ~C1(); +}; + +class C2 { + int x; + int y; +public: + C2(int x, int y): x(x), y(y) {} + int getX() const { return x; } + int getY() const { return y; } + ~C2(); +}; + +void foo(int coin) { + C1 c1 = coin ? C1(1) : C1(2); + if (coin) { +clang_analyzer_eval(c1.getX() == 1); // expected-warning{{TRUE}} + } else { +clang_analyzer_eval(c1.getX() == 2); // expected-warning{{TRUE}} + } + C2 c2 = coin ? C2(3, 4) : C2(5, 6); + if (coin) { +clang_analyzer_eval(c2.getX() == 3); // expected-warning{{TRUE}} +clang_analyzer_eval(c2.getY() == 4); // expected-warning{{TRUE}} + } else { +clang_analyzer_eval(c2.getX() == 5); // expected-warning{{TRUE}} +clang_analyzer_eval(c2.getY() == 6); // expected-warning{{TRUE}} + } +} +} // namespace elision_on_ternary_op_branches + + namespace address_vector_tests { template struct AddressVector { @@ -108,4 +163,68 @@ #endif } +class ClassWithDestructor { + AddressVector + +public: + ClassWithDestructor(AddressVector ) : v(v) { +v.push(this); + } + + ClassWithDestructor(ClassWithDestructor &) : v(c.v) { v.push(this); } + ClassWithDestructor(const ClassWithDestructor ) : v(c.v) { +v.push(this); + } + + ~ClassWithDestructor() { v.push(this); } +}; + +void testVariable() { + AddressVector v; + { +ClassWithDestructor c = ClassWithDestructor(v); + } +#if __cplusplus >= 201703L + // 0. Construct the variable. + // 1. Destroy the variable. + clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}} +#else + // 0. Construct the temporary. + // 1. Construct the variable. + // 2. Destroy the temporary. + // 3. Destroy the variable. + clang_analyzer_eval(v.len == 4); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[1] == v.buf[3]); // expected-warning{{TRUE}} +#endif +} + +struct TestCtorInitializer { + ClassWithDestructor c; + TestCtorInitializer(AddressVector ) +: c(ClassWithDestructor(v)) {} +}; + +void testCtorInitializer() { + AddressVector v; + { +TestCtorInitializer t(v); + } +#if __cplusplus >= 201703L + // 0. Construct the member variable. + // 1. Destroy the member variable. + clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}} +#else + // 0. Construct the temporary. + // 1. Construct the member variable. + // 2. Destroy the temporary. + // 3. Destroy the member variable. + clang_analyzer_eval(v.len == 4); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[1] == v.buf[3]); // expected-warning{{TRUE}} +#endif +} + } // namespace address_vector_tests Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp === --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -119,8 +119,9 @@ // current construction context. if (CC) { switch (CC->getKind()) { +case ConstructionContext::CXX17ElidedCopyVariableKind: case ConstructionContext::SimpleVariableKind: { - const auto *DSCC = cast(CC); + const auto *DSCC = cast(CC); const auto *DS = DSCC->getDeclStmt(); const auto *Var = cast(DS->getSingleDecl()); SVal LValue = State->getLValue(Var, LCtx); @@ -131,6 +132,7 @@ addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, LValue); return std::make_pair(State, LValue); } +case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: case ConstructionContext::SimpleConstructorInitializerKind: { const auto *ICC = cast(CC); const auto *Init = ICC->getCXXCtorInitializer(); @@ -259,9 +261,7 @@ CallOpts.IsTemporaryCtorOrDtor = true; return std::make_pair(State, V); } -
r334683 - [analyzer] Re-enable C++17-specific variable and member construction contexts.
Author: dergachev Date: Wed Jun 13 18:54:21 2018 New Revision: 334683 URL: http://llvm.org/viewvc/llvm-project?rev=334683=rev Log: [analyzer] Re-enable C++17-specific variable and member construction contexts. Not contexts themselves, but rather support for them in the analyzer. Such construction contexts appear when C++17 mandatory copy elision occurs during initialization, and presence of a destructor causes a CXXBindTemporaryExpr to appear in the AST. Similar C++17-specific constructors for return values are still to be supported. Differential Revision: https://reviews.llvm.org/D47351 Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=334683=334682=334683=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Wed Jun 13 18:54:21 2018 @@ -119,8 +119,9 @@ std::pair ExprEng // current construction context. if (CC) { switch (CC->getKind()) { +case ConstructionContext::CXX17ElidedCopyVariableKind: case ConstructionContext::SimpleVariableKind: { - const auto *DSCC = cast(CC); + const auto *DSCC = cast(CC); const auto *DS = DSCC->getDeclStmt(); const auto *Var = cast(DS->getSingleDecl()); SVal LValue = State->getLValue(Var, LCtx); @@ -131,6 +132,7 @@ std::pair ExprEng addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, LValue); return std::make_pair(State, LValue); } +case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: case ConstructionContext::SimpleConstructorInitializerKind: { const auto *ICC = cast(CC); const auto *Init = ICC->getCXXCtorInitializer(); @@ -259,9 +261,7 @@ std::pair ExprEng CallOpts.IsTemporaryCtorOrDtor = true; return std::make_pair(State, V); } -case ConstructionContext::CXX17ElidedCopyVariableKind: case ConstructionContext::CXX17ElidedCopyReturnedValueKind: -case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: // Not implemented yet. break; } Modified: cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp?rev=334683=334682=334683=diff == --- cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp (original) +++ cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp Wed Jun 13 18:54:21 2018 @@ -49,9 +49,64 @@ public: } }; + +struct A { + int x; + A(): x(0) {} + ~A() {} +}; + +struct B { + A a; + B() : a(A()) {} +}; + +void foo() { + B b; + clang_analyzer_eval(b.a.x == 0); // expected-warning{{TRUE}} +} + } // namespace ctor_initializer +namespace elision_on_ternary_op_branches { +class C1 { + int x; +public: + C1(int x): x(x) {} + int getX() const { return x; } + ~C1(); +}; + +class C2 { + int x; + int y; +public: + C2(int x, int y): x(x), y(y) {} + int getX() const { return x; } + int getY() const { return y; } + ~C2(); +}; + +void foo(int coin) { + C1 c1 = coin ? C1(1) : C1(2); + if (coin) { +clang_analyzer_eval(c1.getX() == 1); // expected-warning{{TRUE}} + } else { +clang_analyzer_eval(c1.getX() == 2); // expected-warning{{TRUE}} + } + C2 c2 = coin ? C2(3, 4) : C2(5, 6); + if (coin) { +clang_analyzer_eval(c2.getX() == 3); // expected-warning{{TRUE}} +clang_analyzer_eval(c2.getY() == 4); // expected-warning{{TRUE}} + } else { +clang_analyzer_eval(c2.getX() == 5); // expected-warning{{TRUE}} +clang_analyzer_eval(c2.getY() == 6); // expected-warning{{TRUE}} + } +} +} // namespace elision_on_ternary_op_branches + + namespace address_vector_tests { template struct AddressVector { @@ -108,4 +163,68 @@ void testMultipleReturns() { #endif } +class ClassWithDestructor { + AddressVector + +public: + ClassWithDestructor(AddressVector ) : v(v) { +v.push(this); + } + + ClassWithDestructor(ClassWithDestructor &) : v(c.v) { v.push(this); } + ClassWithDestructor(const ClassWithDestructor ) : v(c.v) { +v.push(this); + } + + ~ClassWithDestructor() { v.push(this); } +}; + +void testVariable() { + AddressVector v; + { +ClassWithDestructor c = ClassWithDestructor(v); + } +#if __cplusplus >= 201703L + // 0. Construct the variable. + // 1. Destroy the variable. + clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}} +#else + // 0. Construct the temporary. + // 1. Construct the variable. + // 2. Destroy the temporary. + // 3. Destroy the variable. + clang_analyzer_eval(v.len == 4); //
[PATCH] D47393: [clang-format] Disable AlwaysBreakBeforeMultilineStrings in Google style for Objective-C
stephanemoore added a comment. Are additional approvals needed to land this? I pinged jolesiak earlier this week asking if he had any comments but have not heard back yet. (also, once necessary approvals have been granted can I request help from someone to land it for me? ) Repository: rC Clang https://reviews.llvm.org/D47393 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r334682 - [analyzer] Track class member initializer constructors path-sensitively.
Author: dergachev Date: Wed Jun 13 18:40:49 2018 New Revision: 334682 URL: http://llvm.org/viewvc/llvm-project?rev=334682=rev Log: [analyzer] Track class member initializer constructors path-sensitively. The reasoning behind this change is similar to the previous commit, r334681. Because members are already in scope when construction occurs, we are not suffering from liveness problems, but we still want to figure out if the object was constructed with construction context, because in this case we'll be able to avoid trivial copy, which we don't always model perfectly. It'd also have more importance when copy elision is implemented. This also gets rid of the old CFG look-behind mechanism. Differential Revision: https://reviews.llvm.org/D47350 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=334682=334681=334682=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Wed Jun 13 18:40:49 2018 @@ -762,20 +762,23 @@ private: /// made within the constructor alive until its declaration actually /// goes into scope. static ProgramStateRef addObjectUnderConstruction( - ProgramStateRef State, const Stmt *S, + ProgramStateRef State, + llvm::PointerUnion P, const LocationContext *LC, SVal V); /// Mark the object sa fully constructed, cleaning up the state trait /// that tracks objects under construction. - static ProgramStateRef finishObjectConstruction(ProgramStateRef State, - const Stmt *S, - const LocationContext *LC); + static ProgramStateRef finishObjectConstruction( + ProgramStateRef State, + llvm::PointerUnion P, + const LocationContext *LC); /// If the given statement corresponds to an object under construction, /// being part of its construciton context, retrieve that object's location. - static Optional getObjectUnderConstruction(ProgramStateRef State, - const Stmt *S, - const LocationContext *LC); + static Optional getObjectUnderConstruction( + ProgramStateRef State, + llvm::PointerUnion P, + const LocationContext *LC); /// Check if all objects under construction have been fully constructed /// for the given context range (including FromLC, not including ToLC). Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=334682=334681=334682=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Jun 13 18:40:49 2018 @@ -109,7 +109,75 @@ STATISTIC(NumTimesRetriedWithoutInlining // to the object's location, so that on every such statement the location // could have been retrieved. -typedef std::pair ConstructedObjectKey; +/// ConstructedObjectKey is used for being able to find the path-sensitive +/// memory region of a freshly constructed object while modeling the AST node +/// that syntactically represents the object that is being constructed. +/// Semantics of such nodes may sometimes require access to the region that's +/// not otherwise present in the program state, or to the very fact that +/// the construction context was present and contained references to these +/// AST nodes. +class ConstructedObjectKey { + typedef std::pair< + llvm::PointerUnion, + const LocationContext *> ConstructedObjectKeyImpl; + + ConstructedObjectKeyImpl Impl; + + const void *getAnyASTNodePtr() const { +if (const Stmt *S = getStmt()) + return S; +else + return getCXXCtorInitializer(); + } + +public: + ConstructedObjectKey( + llvm::PointerUnion P, + const LocationContext *LC) + : Impl(P, LC) { +// This is the full list of statements that require additional actions when +// encountered. This list may be expanded when new actions are implemented. +assert(getCXXCtorInitializer() || isa(getStmt()) || + isa(getStmt()) || isa(getStmt()) || + isa(getStmt())); + } + + const Stmt *getStmt() const { +return Impl.first.dyn_cast(); + } + + const CXXCtorInitializer *getCXXCtorInitializer() const { +return Impl.first.dyn_cast(); + } + +
[PATCH] D47350: [analyzer] Track class member initializer constructors path-sensitively within their construction context.
This revision was automatically updated to reflect the committed changes. Closed by commit rC334682: [analyzer] Track class member initializer constructors path-sensitively. (authored by dergachev, committed by ). Herald added a subscriber: mikhail.ramalho. Repository: rC Clang https://reviews.llvm.org/D47350 Files: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h lib/StaticAnalyzer/Core/ExprEngine.cpp lib/StaticAnalyzer/Core/ExprEngineCXX.cpp test/Analysis/cxx17-mandatory-elision.cpp Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h === --- include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -762,20 +762,23 @@ /// made within the constructor alive until its declaration actually /// goes into scope. static ProgramStateRef addObjectUnderConstruction( - ProgramStateRef State, const Stmt *S, + ProgramStateRef State, + llvm::PointerUnion P, const LocationContext *LC, SVal V); /// Mark the object sa fully constructed, cleaning up the state trait /// that tracks objects under construction. - static ProgramStateRef finishObjectConstruction(ProgramStateRef State, - const Stmt *S, - const LocationContext *LC); + static ProgramStateRef finishObjectConstruction( + ProgramStateRef State, + llvm::PointerUnion P, + const LocationContext *LC); /// If the given statement corresponds to an object under construction, /// being part of its construciton context, retrieve that object's location. - static Optional getObjectUnderConstruction(ProgramStateRef State, - const Stmt *S, - const LocationContext *LC); + static Optional getObjectUnderConstruction( + ProgramStateRef State, + llvm::PointerUnion P, + const LocationContext *LC); /// Check if all objects under construction have been fully constructed /// for the given context range (including FromLC, not including ToLC). Index: test/Analysis/cxx17-mandatory-elision.cpp === --- test/Analysis/cxx17-mandatory-elision.cpp +++ test/Analysis/cxx17-mandatory-elision.cpp @@ -21,6 +21,37 @@ } // namespace variable_functional_cast_crash +namespace ctor_initializer { + +struct S { + int x, y, z; +}; + +struct T { + S s; + int w; + T(int w): s(), w(w) {} +}; + +class C { + T t; +public: + C() : t(T(4)) { +S s = {1, 2, 3}; +t.s = s; +// FIXME: Should be TRUE in C++11 as well. +clang_analyzer_eval(t.w == 4); +#if __cplusplus >= 201703L +// expected-warning@-2{{TRUE}} +#else +// expected-warning@-4{{UNKNOWN}} +#endif + } +}; + +} // namespace ctor_initializer + + namespace address_vector_tests { template struct AddressVector { Index: lib/StaticAnalyzer/Core/ExprEngine.cpp === --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -109,7 +109,75 @@ // to the object's location, so that on every such statement the location // could have been retrieved. -typedef std::pair ConstructedObjectKey; +/// ConstructedObjectKey is used for being able to find the path-sensitive +/// memory region of a freshly constructed object while modeling the AST node +/// that syntactically represents the object that is being constructed. +/// Semantics of such nodes may sometimes require access to the region that's +/// not otherwise present in the program state, or to the very fact that +/// the construction context was present and contained references to these +/// AST nodes. +class ConstructedObjectKey { + typedef std::pair< + llvm::PointerUnion, + const LocationContext *> ConstructedObjectKeyImpl; + + ConstructedObjectKeyImpl Impl; + + const void *getAnyASTNodePtr() const { +if (const Stmt *S = getStmt()) + return S; +else + return getCXXCtorInitializer(); + } + +public: + ConstructedObjectKey( + llvm::PointerUnion P, + const LocationContext *LC) + : Impl(P, LC) { +// This is the full list of statements that require additional actions when +// encountered. This list may be expanded when new actions are implemented. +assert(getCXXCtorInitializer() || isa(getStmt()) || + isa(getStmt()) || isa(getStmt()) || + isa(getStmt())); + } + + const Stmt *getStmt() const { +return Impl.first.dyn_cast(); + } + + const CXXCtorInitializer *getCXXCtorInitializer() const { +return Impl.first.dyn_cast(); + } + + const LocationContext *getLocationContext() const { +return Impl.second; + } + + void print(llvm::raw_ostream , PrinterHelper *Helper, PrintingPolicy ) {
r334681 - [analyzer] pr37270: Track constructor target region, even if just a variable.
Author: dergachev Date: Wed Jun 13 18:32:46 2018 New Revision: 334681 URL: http://llvm.org/viewvc/llvm-project?rev=334681=rev Log: [analyzer] pr37270: Track constructor target region, even if just a variable. The very idea of construction context implies that first the object is constructed, and then later, in a separate moment of time, the constructed object goes into scope, i.e. becomes "live". Most construction contexts require path-sensitive tracking of the constructed object region in order to compute the outer expressions accordingly before the object becomes live. Semantics of simple variable construction contexts don't immediately require that such tracking happens in path-sensitive manner, but shortcomings of the analyzer force us to track it path-sensitively as well. Namely, whether construction context was available at all during construction is a path-sensitive information. Additionally, path-sensitive tracking takes care of our liveness problems that kick in as the temporal gap between construction and going-into-scope becomes larger (eg., due to copy elision). Differential Revision: https://reviews.llvm.org/D47305 Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=334681=334680=334681=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Wed Jun 13 18:32:46 2018 @@ -590,24 +590,12 @@ void ExprEngine::VisitDeclStmt(const Dec SVal InitVal = state->getSVal(InitEx, LC); assert(DS->isSingleDecl()); - if (auto *CtorExpr = findDirectConstructorForCurrentCFGElement()) { -assert(InitEx->IgnoreImplicit() == CtorExpr); -(void)CtorExpr; + if (getObjectUnderConstruction(state, DS, LC)) { +state = finishObjectConstruction(state, DS, LC); // We constructed the object directly in the variable. // No need to bind anything. B.generateNode(DS, UpdatedN, state); } else { -// We bound the temp obj region to the CXXConstructExpr. Now recover -// the lazy compound value when the variable is not a reference. -if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() && -!VD->getType()->isReferenceType()) { - if (Optional M = - InitVal.getAs()) { -InitVal = state->getSVal(M->getRegion()); -assert(InitVal.getAs()); - } -} - // Recover some path-sensitivity if a scalar value evaluated to // UnknownVal. if (InitVal.isUnknown()) { Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=334681=334680=334681=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Wed Jun 13 18:32:46 2018 @@ -125,9 +125,11 @@ std::pair ExprEng const auto *Var = cast(DS->getSingleDecl()); SVal LValue = State->getLValue(Var, LCtx); QualType Ty = Var->getType(); - return std::make_pair( - State, - makeZeroElementRegion(State, LValue, Ty, CallOpts.IsArrayCtorOrDtor)); + LValue = + makeZeroElementRegion(State, LValue, Ty, CallOpts.IsArrayCtorOrDtor); + State = + addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, LValue); + return std::make_pair(State, LValue); } case ConstructionContext::SimpleConstructorInitializerKind: { const auto *ICC = cast(CC); Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=334681=334680=334681=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Wed Jun 13 18:32:46 2018 @@ -193,23 +193,6 @@ static bool wasDifferentDeclUsedForInlin return RuntimeCallee->getCanonicalDecl() != StaticDecl->getCanonicalDecl(); } -/// Returns true if the CXXConstructExpr \p E was intended to construct a -/// prvalue for the region in \p V. -/// -/// Note that we can't just test for rvalue vs. glvalue because -/// CXXConstructExprs embedded in DeclStmts and initializers are considered -/// rvalues by the AST, and the analyzer would like to treat them as lvalues. -static
[PATCH] D47305: [analyzer] pr37270: Fix binding constructed object to DeclStmt when ConstructionContext is already lost.
This revision was automatically updated to reflect the committed changes. Closed by commit rL334681: [analyzer] pr37270: Track constructor target region, even if just a variable. (authored by dergachev, committed by ). Herald added subscribers: llvm-commits, mikhail.ramalho. Changed prior to commit: https://reviews.llvm.org/D47305?vs=148328=151285#toc Repository: rL LLVM https://reviews.llvm.org/D47305 Files: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp Index: cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp === --- cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp +++ cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp @@ -3,6 +3,26 @@ void clang_analyzer_eval(bool); +namespace variable_functional_cast_crash { + +struct A { + A(int) {} +}; + +void foo() { + A a = A(0); +} + +struct B { + A a; + B(): a(A(0)) {} +}; + +} // namespace variable_functional_cast_crash + + +namespace address_vector_tests { + template struct AddressVector { T *buf[10]; int len; @@ -56,3 +76,5 @@ clang_analyzer_eval(v.buf[4] == ); // expected-warning{{TRUE}} #endif } + +} // namespace address_vector_tests Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp === --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -590,24 +590,12 @@ SVal InitVal = state->getSVal(InitEx, LC); assert(DS->isSingleDecl()); - if (auto *CtorExpr = findDirectConstructorForCurrentCFGElement()) { -assert(InitEx->IgnoreImplicit() == CtorExpr); -(void)CtorExpr; + if (getObjectUnderConstruction(state, DS, LC)) { +state = finishObjectConstruction(state, DS, LC); // We constructed the object directly in the variable. // No need to bind anything. B.generateNode(DS, UpdatedN, state); } else { -// We bound the temp obj region to the CXXConstructExpr. Now recover -// the lazy compound value when the variable is not a reference. -if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() && -!VD->getType()->isReferenceType()) { - if (Optional M = - InitVal.getAs()) { -InitVal = state->getSVal(M->getRegion()); -assert(InitVal.getAs()); - } -} - // Recover some path-sensitivity if a scalar value evaluated to // UnknownVal. if (InitVal.isUnknown()) { Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp === --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -125,9 +125,11 @@ const auto *Var = cast(DS->getSingleDecl()); SVal LValue = State->getLValue(Var, LCtx); QualType Ty = Var->getType(); - return std::make_pair( - State, - makeZeroElementRegion(State, LValue, Ty, CallOpts.IsArrayCtorOrDtor)); + LValue = + makeZeroElementRegion(State, LValue, Ty, CallOpts.IsArrayCtorOrDtor); + State = + addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, LValue); + return std::make_pair(State, LValue); } case ConstructionContext::SimpleConstructorInitializerKind: { const auto *ICC = cast(CC); Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp === --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -193,23 +193,6 @@ return RuntimeCallee->getCanonicalDecl() != StaticDecl->getCanonicalDecl(); } -/// Returns true if the CXXConstructExpr \p E was intended to construct a -/// prvalue for the region in \p V. -/// -/// Note that we can't just test for rvalue vs. glvalue because -/// CXXConstructExprs embedded in DeclStmts and initializers are considered -/// rvalues by the AST, and the analyzer would like to treat them as lvalues. -static bool isTemporaryPRValue(const CXXConstructExpr *E, SVal V) { - if (E->isGLValue()) -return false; - - const MemRegion *MR = V.getAsRegion(); - if (!MR) -return false; - - return isa(MR); -} - /// The call exit is simulated with a sequence of nodes, which occur between /// CallExitBegin and CallExitEnd. The following operations occur between the /// two program points: @@ -269,11 +252,7 @@ loc::MemRegionVal This = svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx); SVal ThisV = state->getSVal(This); - - // If the constructed object is a temporary prvalue, get its bindings. - if
[PATCH] D47304: [analyzer] NFC: Merge the functions for obtaining constructed object location and storing this location for later use.
This revision was automatically updated to reflect the committed changes. Closed by commit rC334678: [analyzer] NFC: Merge code for finding and tracking construction target. (authored by dergachev, committed by ). Herald added a subscriber: mikhail.ramalho. Repository: rC Clang https://reviews.llvm.org/D47304 Files: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h lib/StaticAnalyzer/Core/ExprEngine.cpp lib/StaticAnalyzer/Core/ExprEngineCXX.cpp lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h === --- include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -744,14 +744,15 @@ /// constructing into an existing region. const CXXConstructExpr *findDirectConstructorForCurrentCFGElement(); - /// For a given constructor, look forward in the current CFG block to - /// determine the region into which an object will be constructed by \p CE. - /// When the lookahead fails, a temporary region is returned, and the + /// Update the program state with all the path-sensitive information + /// that's necessary to perform construction of an object with a given + /// syntactic construction context. If the construction context is unavailable + /// or unusable for any reason, a dummy temporary region is returned, and the /// IsConstructorWithImproperlyModeledTargetRegion flag is set in \p CallOpts. - SVal getLocationForConstructedObject(const CXXConstructExpr *CE, - ExplodedNode *Pred, - const ConstructionContext *CC, - EvalCallOptions ); + /// Returns the updated program state and the new object's this-region. + std::pair prepareForObjectConstruction( + const Expr *E, ProgramStateRef State, const LocationContext *LCtx, + const ConstructionContext *CC, EvalCallOptions ); /// Store the location of a C++ object corresponding to a statement /// until the statement is actually encountered. For example, if a DeclStmt @@ -782,14 +783,6 @@ static bool areAllObjectsFullyConstructed(ProgramStateRef State, const LocationContext *FromLC, const LocationContext *ToLC); - - /// Adds an initialized temporary and/or a materialization, whichever is - /// necessary, by looking at the whole construction context. Handles - /// function return values, which need the construction context of the parent - /// stack frame, automagically. - ProgramStateRef markStatementsCorrespondingToConstructedObject( - ProgramStateRef State, const ConstructionContext *CC, - const LocationContext *LC, SVal V); }; /// Traits for storing the call processing policy inside GDM. Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp === --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -110,13 +110,9 @@ return LValue; } - -SVal ExprEngine::getLocationForConstructedObject(const CXXConstructExpr *CE, - ExplodedNode *Pred, - const ConstructionContext *CC, - EvalCallOptions ) { - const LocationContext *LCtx = Pred->getLocationContext(); - ProgramStateRef State = Pred->getState(); +std::pair ExprEngine::prepareForObjectConstruction( +const Expr *E, ProgramStateRef State, const LocationContext *LCtx, +const ConstructionContext *CC, EvalCallOptions ) { MemRegionManager = getSValBuilder().getRegionManager(); // See if we're constructing an existing region by looking at the @@ -129,8 +125,9 @@ const auto *Var = cast(DS->getSingleDecl()); SVal LValue = State->getLValue(Var, LCtx); QualType Ty = Var->getType(); - return makeZeroElementRegion(State, LValue, Ty, - CallOpts.IsArrayCtorOrDtor); + return std::make_pair( + State, + makeZeroElementRegion(State, LValue, Ty, CallOpts.IsArrayCtorOrDtor)); } case ConstructionContext::SimpleConstructorInitializerKind: { const auto *ICC = cast(CC); @@ -154,7 +151,7 @@ QualType Ty = Field->getType(); FieldVal = makeZeroElementRegion(State, FieldVal, Ty, CallOpts.IsArrayCtorOrDtor); - return FieldVal; + return std::make_pair(State, FieldVal); } case ConstructionContext::NewAllocatedObjectKind: { if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) { @@ -167,65 +164,97 @@ // TODO: In fact, we need to call the constructor for every // allocated element, not just the first one!
r334678 - [analyzer] NFC: Merge code for finding and tracking construction target.
Author: dergachev Date: Wed Jun 13 18:20:12 2018 New Revision: 334678 URL: http://llvm.org/viewvc/llvm-project?rev=334678=rev Log: [analyzer] NFC: Merge code for finding and tracking construction target. When analyzing C++ code, a common operation in the analyzer is to discover target region for object construction by looking at CFG metadata ("construction contexts"), and then track the region path-sensitively until object construction is resolved, where the amount of information, again, depends on construction context. Scan construction context only once for both purposes. Differential Revision: https://reviews.llvm.org/D47304 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=334678=334677=334678=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Wed Jun 13 18:20:12 2018 @@ -744,14 +744,15 @@ private: /// constructing into an existing region. const CXXConstructExpr *findDirectConstructorForCurrentCFGElement(); - /// For a given constructor, look forward in the current CFG block to - /// determine the region into which an object will be constructed by \p CE. - /// When the lookahead fails, a temporary region is returned, and the + /// Update the program state with all the path-sensitive information + /// that's necessary to perform construction of an object with a given + /// syntactic construction context. If the construction context is unavailable + /// or unusable for any reason, a dummy temporary region is returned, and the /// IsConstructorWithImproperlyModeledTargetRegion flag is set in \p CallOpts. - SVal getLocationForConstructedObject(const CXXConstructExpr *CE, - ExplodedNode *Pred, - const ConstructionContext *CC, - EvalCallOptions ); + /// Returns the updated program state and the new object's this-region. + std::pair prepareForObjectConstruction( + const Expr *E, ProgramStateRef State, const LocationContext *LCtx, + const ConstructionContext *CC, EvalCallOptions ); /// Store the location of a C++ object corresponding to a statement /// until the statement is actually encountered. For example, if a DeclStmt @@ -782,14 +783,6 @@ private: static bool areAllObjectsFullyConstructed(ProgramStateRef State, const LocationContext *FromLC, const LocationContext *ToLC); - - /// Adds an initialized temporary and/or a materialization, whichever is - /// necessary, by looking at the whole construction context. Handles - /// function return values, which need the construction context of the parent - /// stack frame, automagically. - ProgramStateRef markStatementsCorrespondingToConstructedObject( - ProgramStateRef State, const ConstructionContext *CC, - const LocationContext *LC, SVal V); }; /// Traits for storing the call processing policy inside GDM. Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=334678=334677=334678=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Jun 13 18:20:12 2018 @@ -417,81 +417,6 @@ bool ExprEngine::areAllObjectsFullyConst return true; } -ProgramStateRef ExprEngine::markStatementsCorrespondingToConstructedObject( -ProgramStateRef State, const ConstructionContext *CC, -const LocationContext *LC, SVal V) { - if (CC) { -// If the temporary is being returned from the function, it will be -// destroyed or lifetime-extended in the caller stack frame. -if (isa(CC)) { - const StackFrameContext *SFC = LC->getCurrentStackFrame(); - assert(SFC); - LC = SFC->getParent(); - if (!LC) { -// We are on the top frame. We won't ever need any info -// for this temporary, so don't set anything. -return State; - } - const CFGElement = - (*SFC->getCallSiteBlock())[SFC->getIndex()]; - auto RTCElem = CallElem.getAs(); - if (!RTCElem) { -// We have a parent stack frame, but no construction context for the -// return value. Give up until we provide the construction context -
[PATCH] D48155: Teach Clang to emit address-significance tables.
pcc updated this revision to Diff 151282. pcc added a comment. - Add some additional driver tests https://reviews.llvm.org/D48155 Files: clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/CodeGen/addrsig.c clang/test/Driver/addrsig.c Index: clang/test/Driver/addrsig.c === --- /dev/null +++ clang/test/Driver/addrsig.c @@ -0,0 +1,8 @@ +// RUN: %clang -### -target x86_64-unknown-linux -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s +// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s +// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -faddrsig -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s +// RUN: %clang -### -target x86_64-unknown-linux -fno-addrsig -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s +// RUN: %clang -### -target x86_64-apple-darwin -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s + +// ADDRSIG: -faddrsig +// NO-ADDRSIG-NOT: -faddrsig Index: clang/test/CodeGen/addrsig.c === --- /dev/null +++ clang/test/CodeGen/addrsig.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -faddrsig -O -o - | FileCheck --check-prefix=ADDRSIG %s +// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -O -o - | FileCheck --check-prefix=NO-ADDRSIG %s + +// ADDRSIG: .addrsig +// ADDRSIG: .addrsig_sym g1 +// ADDRSIG-NOT: .addrsig_sym g2 + +// NO-ADDRSIG-NOT: .addrsig + +extern const int g1[], g2[]; + +const int *f1() { + return g1; +} + +int f2() { + return g2[0]; +} Index: clang/lib/Frontend/CompilerInvocation.cpp === --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -1119,6 +1119,8 @@ Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); + Opts.Addrsig = Args.hasArg(OPT_faddrsig); + return Success; } Index: clang/lib/Driver/ToolChains/Clang.cpp === --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -4798,6 +4798,11 @@ options::OPT_fno_complete_member_pointers, false)) CmdArgs.push_back("-fcomplete-member-pointers"); + if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig, + getToolChain().getTriple().isOSBinFormatELF() && + getToolChain().useIntegratedAs())) +CmdArgs.push_back("-faddrsig"); + // Finally add the compile command to the compilation. if (Args.hasArg(options::OPT__SLASH_fallback) && Output.getType() == types::TY_Object && Index: clang/lib/CodeGen/BackendUtil.cpp === --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -454,6 +454,7 @@ Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS; Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning(); Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection; + Options.EmitAddrsig = CodeGenOpts.Addrsig; if (CodeGenOpts.EnableSplitDwarf) Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; Index: clang/include/clang/Frontend/CodeGenOptions.def === --- clang/include/clang/Frontend/CodeGenOptions.def +++ clang/include/clang/Frontend/CodeGenOptions.def @@ -335,6 +335,9 @@ /// Whether to emit all vtables CODEGENOPT(ForceEmitVTables, 1, 0) +/// Whether to emit an address-significance table into the object file. +CODEGENOPT(Addrsig, 1, 0) + #undef CODEGENOPT #undef ENUM_CODEGENOPT Index: clang/include/clang/Driver/Options.td === --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -758,6 +758,10 @@ def fno_profile_use : Flag<["-"], "fno-profile-use">, Alias; +def faddrsig : Flag<["-"], "faddrsig">, Group, Flags<[CoreOption, CC1Option]>, + HelpText<"Emit an address-significance table">; +def fno_addrsig : Flag<["-"], "fno-addrsig">, Group, Flags<[CoreOption]>, + HelpText<"Don't emit an address-significance table">; def fblocks : Flag<["-"], "fblocks">, Group, Flags<[CC1Option]>, HelpText<"Enable the 'blocks' language feature">; def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48155: Teach Clang to emit address-significance tables.
pcc created this revision. pcc added reviewers: echristo, Bigcheese, rsmith. By default, we emit an address-significance table on all ELF targets when the integrated assembler is enabled. The emission of an address-significance table can be controlled with the -faddrsig and -fno-addrsig flags. Depends on https://reviews.llvm.org/D48143 https://reviews.llvm.org/D48155 Files: clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/CodeGen/addrsig.c clang/test/Driver/addrsig.c Index: clang/test/Driver/addrsig.c === --- /dev/null +++ clang/test/Driver/addrsig.c @@ -0,0 +1,6 @@ +// RUN: %clang -### -target x86_64-unknown-linux -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s +// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -gz -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s +// RUN: %clang -### -target x86_64-apple-darwin -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s + +// ADDRSIG: -faddrsig +// NO-ADDRSIG-NOT: -faddrsig Index: clang/test/CodeGen/addrsig.c === --- /dev/null +++ clang/test/CodeGen/addrsig.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -faddrsig -O -o - | FileCheck --check-prefix=ADDRSIG %s +// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -O -o - | FileCheck --check-prefix=NO-ADDRSIG %s + +// ADDRSIG: .addrsig +// ADDRSIG: .addrsig_sym g1 +// ADDRSIG-NOT: .addrsig_sym g2 + +// NO-ADDRSIG-NOT: .addrsig + +extern const int g1[], g2[]; + +const int *f1() { + return g1; +} + +int f2() { + return g2[0]; +} Index: clang/lib/Frontend/CompilerInvocation.cpp === --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -1119,6 +1119,8 @@ Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); + Opts.Addrsig = Args.hasArg(OPT_faddrsig); + return Success; } Index: clang/lib/Driver/ToolChains/Clang.cpp === --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -4798,6 +4798,11 @@ options::OPT_fno_complete_member_pointers, false)) CmdArgs.push_back("-fcomplete-member-pointers"); + if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig, + getToolChain().getTriple().isOSBinFormatELF() && + getToolChain().useIntegratedAs())) +CmdArgs.push_back("-faddrsig"); + // Finally add the compile command to the compilation. if (Args.hasArg(options::OPT__SLASH_fallback) && Output.getType() == types::TY_Object && Index: clang/lib/CodeGen/BackendUtil.cpp === --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -454,6 +454,7 @@ Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS; Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning(); Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection; + Options.EmitAddrsig = CodeGenOpts.Addrsig; if (CodeGenOpts.EnableSplitDwarf) Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; Index: clang/include/clang/Frontend/CodeGenOptions.def === --- clang/include/clang/Frontend/CodeGenOptions.def +++ clang/include/clang/Frontend/CodeGenOptions.def @@ -335,6 +335,9 @@ /// Whether to emit all vtables CODEGENOPT(ForceEmitVTables, 1, 0) +/// Whether to emit an address-significance table into the object file. +CODEGENOPT(Addrsig, 1, 0) + #undef CODEGENOPT #undef ENUM_CODEGENOPT Index: clang/include/clang/Driver/Options.td === --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -758,6 +758,10 @@ def fno_profile_use : Flag<["-"], "fno-profile-use">, Alias; +def faddrsig : Flag<["-"], "faddrsig">, Group, Flags<[CoreOption, CC1Option]>, + HelpText<"Emit an address-significance table">; +def fno_addrsig : Flag<["-"], "fno-addrsig">, Group, Flags<[CoreOption]>, + HelpText<"Don't emit an address-significance table">; def fblocks : Flag<["-"], "fblocks">, Group, Flags<[CC1Option]>, HelpText<"Enable the 'blocks' language feature">; def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47671: [analyzer] Implement copy elision.
NoQ added a comment. > P.S. It seems that one of my currently-on-review patches has introduced a > performance regression, i'm investigating it. Never mind, that was an old version of the patch, i.e. i accidentally fixed that regression before uploading the patch to phabricator. https://reviews.llvm.org/D47671 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47671: [analyzer] Implement copy elision.
NoQ updated this revision to Diff 151279. NoQ added a comment. I added an option to disable copy elision on CFG side in https://reviews.llvm.org/D47616. The analyzer makes use of it automagically: elided constructors are replaced with temporary constructors in the CFG and the old behavior is restored. Tests now test both behaviors and demonstrate that C++17 mandatory copy elision works exactly like pre-C++17 optional copy elision, despite underlying AST being completely different. Well, most of the time: there's still a bug that causes us to think that we need to call a destructor on the elided temporary. Thankfully, such destructor would be evaluated conservatively. https://reviews.llvm.org/D47671 Files: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h lib/StaticAnalyzer/Core/ExprEngine.cpp lib/StaticAnalyzer/Core/ExprEngineCXX.cpp test/Analysis/cxx17-mandatory-elision.cpp test/Analysis/gtest.cpp test/Analysis/inlining/temp-dtors-path-notes.cpp test/Analysis/lifetime-extension.cpp test/Analysis/temporaries.cpp Index: test/Analysis/temporaries.cpp === --- test/Analysis/temporaries.cpp +++ test/Analysis/temporaries.cpp @@ -612,107 +612,44 @@ clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}} C c4 = returnTemporaryWithConstruction(); - clang_analyzer_eval(c4.getX() == 1); - clang_analyzer_eval(c4.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c4.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c4.getY() == 2); // expected-warning{{TRUE}} C c5 = returnTemporaryWithAnotherFunctionWithConstruction(); - clang_analyzer_eval(c5.getX() == 1); - clang_analyzer_eval(c5.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}} C c6 = returnTemporaryWithCopyConstructionWithConstruction(); - clang_analyzer_eval(c5.getX() == 1); - clang_analyzer_eval(c5.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}} #if __cplusplus >= 201103L C c7 = returnTemporaryWithBraces(); - clang_analyzer_eval(c7.getX() == 1); - clang_analyzer_eval(c7.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c7.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c7.getY() == 2); // expected-warning{{TRUE}} C c8 = returnTemporaryWithAnotherFunctionWithBraces(); - clang_analyzer_eval(c8.getX() == 1); - clang_analyzer_eval(c8.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c8.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c8.getY() == 2); // expected-warning{{TRUE}} C c9 = returnTemporaryWithCopyConstructionWithBraces(); - clang_analyzer_eval(c9.getX() == 1); - clang_analyzer_eval(c9.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c9.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c9.getY() == 2); // expected-warning{{TRUE}} #endif // C++11 D d1 = returnTemporaryWithVariableAndNonTrivialCopy(); - clang_analyzer_eval(d1.getX() == 1); - clang_analyzer_eval(d1.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(d1.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(d1.getY() == 2); // expected-warning{{TRUE}} D d2 = returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy(); - clang_analyzer_eval(d2.getX() == 1); - clang_analyzer_eval(d2.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(d2.getX() == 1); // expected-warning{{TRUE}} +
[PATCH] D47616: [CFG] [analyzer] Explain copy elision through construction contexts.
NoQ updated this revision to Diff 151277. NoQ added a comment. Add a flag to disable copy elision. It's convenient to have such flag in the CFG because this way all clients will be able to transparently handle it. When the option is turned off, elided construction contexts will be replaced with simple temporary object construction contexts which need to be handled anyway. When construction contexts are disabled entirely, the option has no effect. https://reviews.llvm.org/D47616 Files: include/clang/Analysis/AnalysisDeclContext.h include/clang/Analysis/CFG.h include/clang/Analysis/ConstructionContext.h include/clang/StaticAnalyzer/Core/AnalyzerOptions.h lib/Analysis/AnalysisDeclContext.cpp lib/Analysis/CFG.cpp lib/Analysis/ConstructionContext.cpp lib/StaticAnalyzer/Core/AnalysisManager.cpp lib/StaticAnalyzer/Core/AnalyzerOptions.cpp lib/StaticAnalyzer/Core/ExprEngineCXX.cpp test/Analysis/analyzer-config.c test/Analysis/analyzer-config.cpp test/Analysis/cfg-rich-constructors.cpp test/Analysis/temp-obj-dtors-cfg-output.cpp Index: test/Analysis/temp-obj-dtors-cfg-output.cpp === --- test/Analysis/temp-obj-dtors-cfg-output.cpp +++ test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -235,7 +235,7 @@ // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -295,7 +295,7 @@ // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -550,12 +550,12 @@ // CHECK: Succs (2): B6 B5 // CHECK: [B8] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B8.2], [B8.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B8.2], [B8.4], [B8.5], class A) // CHECK: 2: [B8.1] (BindTemporary) // CHECK: 3: [B8.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B8.3] // WARNINGS: 5: [B8.4] (CXXConstructExpr, class A) -// ANALYZER: 5: [B8.4] (CXXConstructExpr, [B8.6], [B7.3], class A) +// ANALYZER: 5: [B8.4] (CXXConstructExpr, [B8.6], [B7.3], [B7.4], class A) // CHECK: 6: [B8.5] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 @@ -570,13 +570,13 @@ // CHECK: 7: [B9.6] (ImplicitCastExpr, NoOp, const class A) // CHECK: 8: [B9.7] // WARNINGS: 9: [B9.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B9.8] (CXXConstructExpr, [B9.10], [B9.13], class A) +// ANALYZER: 9: [B9.8] (CXXConstructExpr, [B9.10], [B9.13], [B9.14], class A) // CHECK:10: [B9.9] (BindTemporary) // CHECK:11: A([B9.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) // CHECK:12: [B9.11] (ImplicitCastExpr, NoOp, const class A) // CHECK:13: [B9.12] // WARNINGS:14: [B9.13] (CXXConstructExpr, class A) -// ANALYZER:14: [B9.13] (CXXConstructExpr, [B9.15], [B7.3], class A) +// ANALYZER:14: [B9.13] (CXXConstructExpr, [B9.15], [B7.3], [B7.4], class A) // CHECK:15: [B9.14] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 @@ -680,7 +680,7 @@ // CHECK: Succs (1): B0 // CHECK: [B4] // WARNINGS: 1: C() (CXXConstructExpr, struct C) -// ANALYZER: 1: C() (CXXConstructExpr, [B4.2], [B4.4], struct C) +// ANALYZER: 1: C() (CXXConstructExpr, [B4.2], [B4.4], [B4.5], struct C) // CHECK: 2: [B4.1] (BindTemporary) // CHECK: 3: [B4.2] (ImplicitCastExpr, NoOp, const struct C) // CHECK: 4: [B4.3] @@ -733,7 +733,7 @@ // CHECK: Succs (1): B0 // CHECK: [B3] // CXX98-WARNINGS: 1: D() (CXXConstructExpr, struct D) -// CXX98-ANALYZER: 1: D() (CXXConstructExpr, [B3.3], struct D) +// CXX98-ANALYZER: 1: D() (CXXConstructExpr, [B3.3], [B3.4], struct D) // CXX98: 2: [B3.1] (ImplicitCastExpr, NoOp, const struct D) // CXX98: 3: [B3.2] // CXX98-WARNINGS: 4: [B3.3] (CXXConstructExpr, struct D) @@ -745,7 +745,7 @@ // CXX98: 9: [B3.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CXX98: T: if [B3.9] // CXX11-WARNINGS: 1: D() (CXXConstructExpr, struct D) -// CXX11-ANALYZER: 1: D() (CXXConstructExpr, [B3.2], struct D) +// CXX11-ANALYZER: 1: D() (CXXConstructExpr, [B3.2], [B3.3], struct D) // CXX11: 2: [B3.1] // CXX11-WARNINGS: 3: [B3.2] (CXXConstructExpr, struct D) // CXX11-ANALYZER: 3: [B3.2] (CXXConstructExpr, [B3.4], struct D) @@ -789,7 +789,7 @@ // CHECK:
[PATCH] D47616: [CFG] [analyzer] Explain copy elision through construction contexts.
NoQ added inline comments. Comment at: include/clang/Analysis/ConstructionContext.h:351 + + explicit SimpleTemporaryObjectConstructionContext( + const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE) MTC wrote: > MTC wrote: > > `explicit` useless? > I'm wrong here, maybe there is some use of > `SimpleTemporaryObjectConstructionContext({ , })`, sorry to bother! Well, i really doubt it'd ever matter (given that the constructor is also private, we can pretty much control all constructions by hand) but i think it's a good practice to add the restriction unless implicit construction is actually important. https://reviews.llvm.org/D47616 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47667: [CFG] [analyzer] Remove unnecessary CXXBindTemporaryExpr from lifetime-extended temporary construction contexts.
NoQ updated this revision to Diff 151278. NoQ added a comment. Herald added a subscriber: mikhail.ramalho. Rebase. https://reviews.llvm.org/D47667 Files: lib/Analysis/ConstructionContext.cpp lib/StaticAnalyzer/Core/ExprEngineCXX.cpp test/Analysis/auto-obj-dtors-cfg-output.cpp test/Analysis/cfg-rich-constructors.cpp test/Analysis/temp-obj-dtors-cfg-output.cpp Index: test/Analysis/temp-obj-dtors-cfg-output.cpp === --- test/Analysis/temp-obj-dtors-cfg-output.cpp +++ test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -857,7 +857,7 @@ // CHECK: 3: [B11.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B11.3] // WARNINGS: 5: [B11.4] (CXXConstructExpr, class A) -// ANALYZER: 5: [B11.4] (CXXConstructExpr, [B11.6], [B10.3], class A) +// ANALYZER: 5: [B11.4] (CXXConstructExpr, [B10.3], class A) // CHECK: 6: [B11.5] (BindTemporary) // CHECK: Preds (1): B13 // CHECK: Succs (1): B10 @@ -878,7 +878,7 @@ // CHECK:12: [B12.11] (ImplicitCastExpr, NoOp, const class A) // CHECK:13: [B12.12] // WARNINGS:14: [B12.13] (CXXConstructExpr, class A) -// ANALYZER:14: [B12.13] (CXXConstructExpr, [B12.15], [B10.3], class A) +// ANALYZER:14: [B12.13] (CXXConstructExpr, [B10.3], class A) // CHECK:15: [B12.14] (BindTemporary) // CHECK: Preds (1): B13 // CHECK: Succs (1): B10 @@ -1104,7 +1104,7 @@ // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.4], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -1150,7 +1150,7 @@ // CHECK: 1: A::make // CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) // WARNINGS: 3: [B1.2]() -// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) +// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.6]) // CHECK: 4: [B1.3] (BindTemporary) // CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A) // CHECK: 6: [B1.5] Index: test/Analysis/cfg-rich-constructors.cpp === --- test/Analysis/cfg-rich-constructors.cpp +++ test/Analysis/cfg-rich-constructors.cpp @@ -597,7 +597,7 @@ // CHECK: void referenceVariableWithConstructor() // CHECK: 1: 0 -// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], [B1.4], const class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.4], const class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 3: [B1.2] (BindTemporary) // CHECK-NEXT: 4: [B1.3] // CHECK-NEXT: 5: const temporary_object_expr_with_dtors::D (0); @@ -607,7 +607,7 @@ } // CHECK: void referenceVariableWithInitializer() -// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.2], [B1.4], class temporary_object_expr_with_dtors::D) +// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.4], class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 2: [B1.1] (BindTemporary) // CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 4: [B1.3] @@ -638,7 +638,7 @@ // CXX11-NEXT: 4: [B5.3] (BindTemporary) // CXX11-NEXT: 5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 6: [B5.5] -// CXX11-NEXT: 7: [B5.6] (CXXConstructExpr, [B5.8], [B4.3], class temporary_object_expr_with_dtors::D) +// CXX11-NEXT: 7: [B5.6] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 8: [B5.7] (BindTemporary) // CXX11:[B6] // CXX11-NEXT: 1: 0 @@ -648,7 +648,7 @@ // CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 6: [B6.5] -// CXX11-NEXT: 7: [B6.6] (CXXConstructExpr, [B6.8], [B4.3], class temporary_object_expr_with_dtors::D) +// CXX11-NEXT: 7: [B6.6] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 8: [B6.7] (BindTemporary) // CXX11:[B7] // CXX11-NEXT: 1: coin @@ -663,11 +663,11 @@ // CXX17:[B2] // CXX17-NEXT: 1: D::get // CXX17-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void)) -// CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B1.3]) +// CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B1.3]) // CXX17-NEXT: 4: [B2.3] (BindTemporary) // CXX17:[B3] // CXX17-NEXT: 1: 0 -// CXX17-NEXT: 2: [B3.1]
r334677 - P0096R5, P0941R2: Update to match latest feature test macro specification.
Author: rsmith Date: Wed Jun 13 17:40:20 2018 New Revision: 334677 URL: http://llvm.org/viewvc/llvm-project?rev=334677=rev Log: P0096R5, P0941R2: Update to match latest feature test macro specification. Modified: cfe/trunk/lib/Frontend/InitPreprocessor.cpp cfe/trunk/test/Lexer/cxx-features.cpp cfe/trunk/www/cxx_status.html Modified: cfe/trunk/lib/Frontend/InitPreprocessor.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/InitPreprocessor.cpp?rev=334677=334676=334677=diff == --- cfe/trunk/lib/Frontend/InitPreprocessor.cpp (original) +++ cfe/trunk/lib/Frontend/InitPreprocessor.cpp Wed Jun 13 17:40:20 2018 @@ -487,82 +487,86 @@ static void InitializeCPlusPlusFeatureTe MacroBuilder ) { // C++98 features. if (LangOpts.RTTI) -Builder.defineMacro("__cpp_rtti", "199711"); +Builder.defineMacro("__cpp_rtti", "199711L"); if (LangOpts.CXXExceptions) -Builder.defineMacro("__cpp_exceptions", "199711"); +Builder.defineMacro("__cpp_exceptions", "199711L"); // C++11 features. if (LangOpts.CPlusPlus11) { -Builder.defineMacro("__cpp_unicode_characters", "200704"); -Builder.defineMacro("__cpp_raw_strings", "200710"); -Builder.defineMacro("__cpp_unicode_literals", "200710"); -Builder.defineMacro("__cpp_user_defined_literals", "200809"); -Builder.defineMacro("__cpp_lambdas", "200907"); +Builder.defineMacro("__cpp_unicode_characters", "200704L"); +Builder.defineMacro("__cpp_raw_strings", "200710L"); +Builder.defineMacro("__cpp_unicode_literals", "200710L"); +Builder.defineMacro("__cpp_user_defined_literals", "200809L"); +Builder.defineMacro("__cpp_lambdas", "200907L"); Builder.defineMacro("__cpp_constexpr", -LangOpts.CPlusPlus17 ? "201603" : -LangOpts.CPlusPlus14 ? "201304" : "200704"); +LangOpts.CPlusPlus17 ? "201603L" : +LangOpts.CPlusPlus14 ? "201304L" : "200704"); Builder.defineMacro("__cpp_range_based_for", -LangOpts.CPlusPlus17 ? "201603" : "200907"); +LangOpts.CPlusPlus17 ? "201603L" : "200907"); Builder.defineMacro("__cpp_static_assert", -LangOpts.CPlusPlus17 ? "201411" : "200410"); -Builder.defineMacro("__cpp_decltype", "200707"); -Builder.defineMacro("__cpp_attributes", "200809"); -Builder.defineMacro("__cpp_rvalue_references", "200610"); -Builder.defineMacro("__cpp_variadic_templates", "200704"); -Builder.defineMacro("__cpp_initializer_lists", "200806"); -Builder.defineMacro("__cpp_delegating_constructors", "200604"); -Builder.defineMacro("__cpp_nsdmi", "200809"); -Builder.defineMacro("__cpp_inheriting_constructors", "201511"); -Builder.defineMacro("__cpp_ref_qualifiers", "200710"); -Builder.defineMacro("__cpp_alias_templates", "200704"); +LangOpts.CPlusPlus17 ? "201411L" : "200410"); +Builder.defineMacro("__cpp_decltype", "200707L"); +Builder.defineMacro("__cpp_attributes", "200809L"); +Builder.defineMacro("__cpp_rvalue_references", "200610L"); +Builder.defineMacro("__cpp_variadic_templates", "200704L"); +Builder.defineMacro("__cpp_initializer_lists", "200806L"); +Builder.defineMacro("__cpp_delegating_constructors", "200604L"); +Builder.defineMacro("__cpp_nsdmi", "200809L"); +Builder.defineMacro("__cpp_inheriting_constructors", "201511L"); +Builder.defineMacro("__cpp_ref_qualifiers", "200710L"); +Builder.defineMacro("__cpp_alias_templates", "200704L"); } if (LangOpts.ThreadsafeStatics) -Builder.defineMacro("__cpp_threadsafe_static_init", "200806"); +Builder.defineMacro("__cpp_threadsafe_static_init", "200806L"); // C++14 features. if (LangOpts.CPlusPlus14) { -Builder.defineMacro("__cpp_binary_literals", "201304"); -Builder.defineMacro("__cpp_digit_separators", "201309"); -Builder.defineMacro("__cpp_init_captures", "201304"); -Builder.defineMacro("__cpp_generic_lambdas", "201304"); -Builder.defineMacro("__cpp_decltype_auto", "201304"); -Builder.defineMacro("__cpp_return_type_deduction", "201304"); -Builder.defineMacro("__cpp_aggregate_nsdmi", "201304"); -Builder.defineMacro("__cpp_variable_templates", "201304"); +Builder.defineMacro("__cpp_binary_literals", "201304L"); +Builder.defineMacro("__cpp_digit_separators", "201309L"); +Builder.defineMacro("__cpp_init_captures", "201304L"); +Builder.defineMacro("__cpp_generic_lambdas", "201304L"); +Builder.defineMacro("__cpp_decltype_auto", "201304L"); +Builder.defineMacro("__cpp_return_type_deduction", "201304L"); +Builder.defineMacro("__cpp_aggregate_nsdmi", "201304L"); +Builder.defineMacro("__cpp_variable_templates", "201304L"); } if (LangOpts.SizedDeallocation) -
[PATCH] D47658: [analyzer] Re-enable lifetime extension for temporaries with destructors and bring back static temporaries.
NoQ updated this revision to Diff 151276. NoQ marked an inline comment as done. NoQ added a comment. Herald added a subscriber: mikhail.ramalho. Fxd. https://reviews.llvm.org/D47658 Files: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp test/Analysis/lifetime-extension.cpp test/Analysis/temporaries-callback-order.cpp Index: test/Analysis/temporaries-callback-order.cpp === --- test/Analysis/temporaries-callback-order.cpp +++ test/Analysis/temporaries-callback-order.cpp @@ -8,11 +8,7 @@ }; void testTemporaries() { - // This triggers RegionChanges twice: - // - Once for zero-initialization of the structure. - // - Once for creating a temporary region and copying the structure there. - // FIXME: This code shouldn't really produce the extra temporary, however - // that's how we behave for now. + // This triggers RegionChanges once for zero-initialization of the structure. Sub().m(); } @@ -29,7 +25,6 @@ // testTemporaries(): // CHECK-NEXT: RegionChanges -// CHECK-NEXT: RegionChanges // Make sure there's no further output. // CHECK-NOT: Bind Index: test/Analysis/lifetime-extension.cpp === --- test/Analysis/lifetime-extension.cpp +++ test/Analysis/lifetime-extension.cpp @@ -234,25 +234,24 @@ } // end namespace maintain_original_object_address_on_move namespace maintain_address_of_copies { -class C; -struct AddressVector { - C *buf[10]; +template struct AddressVector { + const T *buf[10]; int len; AddressVector() : len(0) {} - void push(C *c) { -buf[len] = c; + void push(const T *t) { +buf[len] = t; ++len; } }; class C { - AddressVector + AddressVector public: - C(AddressVector ) : v(v) { v.push(this); } + C(AddressVector ) : v(v) { v.push(this); } ~C() { v.push(this); } #ifdef MOVES @@ -268,11 +267,11 @@ #endif } // no-warning - static C make(AddressVector ) { return C(v); } + static C make(AddressVector ) { return C(v); } }; void f1() { - AddressVector v; + AddressVector v; { C c = C(v); } @@ -296,7 +295,7 @@ } void f2() { - AddressVector v; + AddressVector v; { const C = C::make(v); } @@ -320,7 +319,7 @@ } void f3() { - AddressVector v; + AddressVector v; { C & = C::make(v); } @@ -343,12 +342,12 @@ #endif } -C doubleMake(AddressVector ) { +C doubleMake(AddressVector ) { return C::make(v); } void f4() { - AddressVector v; + AddressVector v; { C c = doubleMake(v); } @@ -382,4 +381,18 @@ // expected-warning@-12{{UNKNOWN}} #endif } + +class NoDtor { + AddressVector + +public: + NoDtor(AddressVector ) : v(v) { v.push(this); } +}; + +void f5() { + AddressVector v; + const NoDtor = NoDtor(v); + clang_analyzer_eval(v.buf[0] == ); // expected-warning{{TRUE}} +} + } // end namespace maintain_address_of_copies Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp === --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -214,12 +214,6 @@ const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); - if (!BTE) { -// FIXME: Lifetime extension for temporaries without destructors -// is not implemented yet. -MTE = nullptr; - } - if (MTE) { if (const ValueDecl *VD = MTE->getExtendingDecl()) { assert(MTE->getStorageDuration() != SD_FullExpression); @@ -234,16 +228,20 @@ } } + SVal V = UnknownVal(); if (MTE && MTE->getStorageDuration() != SD_FullExpression) { // If the temporary is lifetime-extended, don't save the BTE, // because we don't need a temporary destructor, but an automatic // destructor. BTE = nullptr; + +if (MTE->getStorageDuration() == SD_Static || +MTE->getStorageDuration() == SD_Thread) + V = loc::MemRegionVal(MRMgr.getCXXStaticTempObjectRegion(E)); } - // FIXME: Support temporaries lifetime-extended via static references. - // They'd need a getCXXStaticTempObjectRegion(). - SVal V = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); + if (V.isUnknown()) +V = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); if (BTE) State = addObjectUnderConstruction(State, BTE, LCtx, V); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47658: [analyzer] Re-enable lifetime extension for temporaries with destructors and bring back static temporaries.
NoQ added inline comments. Comment at: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp:234 + SVal V = UnknownVal(); + if (MTE) { +if (MTE->getStorageDuration() != SD_FullExpression) { MTC wrote: > An unrelated question. I want to know, what considerations are you based on > not continue to use short circuit style : )? Whoops accidental^^ https://reviews.llvm.org/D47658 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[libcxx] r334675 - [libcxx] [test] Update msvc_stdlib_force_include.hpp.
Author: stl_msft Date: Wed Jun 13 17:12:14 2018 New Revision: 334675 URL: http://llvm.org/viewvc/llvm-project?rev=334675=rev Log: [libcxx] [test] Update msvc_stdlib_force_include.hpp. MSVC's STL removed _SCL_SECURE_NO_WARNINGS. MSVC's STL implemented feature-test macros. Modified: libcxx/trunk/test/support/msvc_stdlib_force_include.hpp Modified: libcxx/trunk/test/support/msvc_stdlib_force_include.hpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/msvc_stdlib_force_include.hpp?rev=334675=334674=334675=diff == --- libcxx/trunk/test/support/msvc_stdlib_force_include.hpp (original) +++ libcxx/trunk/test/support/msvc_stdlib_force_include.hpp Wed Jun 13 17:12:14 2018 @@ -73,9 +73,6 @@ const AssertionDialogAvoider assertion_d // atomic_is_lock_free.pass.cpp needs this VS 2015 Update 2 fix. #define _ENABLE_ATOMIC_ALIGNMENT_FIX -// Silence warnings about raw pointers and other unchecked iterators. -#define _SCL_SECURE_NO_WARNINGS - // Silence warnings about features that are deprecated in C++17. #define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS #endif // _LIBCXX_IN_DEVCRT @@ -88,12 +85,4 @@ const AssertionDialogAvoider assertion_d #define TEST_STD_VER 14 #endif // _HAS_CXX17 -// Simulate library feature-test macros. -#define __cpp_lib_invoke 201411 -#define __cpp_lib_void_t 201411 - -#if _HAS_CXX17 -#define __cpp_lib_atomic_is_always_lock_free 201603 -#endif // _HAS_CXX17 - #endif // SUPPORT_MSVC_STDLIB_FORCE_INCLUDE_HPP ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[libcxx] r334676 - [libcxx] [test] Strip trailing whitespace. NFC.
Author: stl_msft Date: Wed Jun 13 17:12:20 2018 New Revision: 334676 URL: http://llvm.org/viewvc/llvm-project?rev=334676=rev Log: [libcxx] [test] Strip trailing whitespace. NFC. Modified: libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.fail.cpp libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp libcxx/trunk/test/std/containers/container.adaptors/queue/queue.cons/deduct.fail.cpp libcxx/trunk/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp libcxx/trunk/test/std/containers/container.adaptors/stack/stack.cons/deduct.fail.cpp libcxx/trunk/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp libcxx/trunk/test/std/containers/sequences/deque/deque.cons/deduct.fail.cpp libcxx/trunk/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.fail.cpp libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp libcxx/trunk/test/std/containers/sequences/list/list.cons/deduct.fail.cpp libcxx/trunk/test/std/containers/sequences/list/list.cons/deduct.pass.cpp libcxx/trunk/test/std/containers/sequences/vector/vector.cons/deduct.fail.cpp libcxx/trunk/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp libcxx/trunk/test/std/language.support/support.exception/uncaught/uncaught_exceptions.pass.cpp libcxx/trunk/test/std/re/re.regex/re.regex.construct/deduct.fail.cpp libcxx/trunk/test/std/re/re.regex/re.regex.construct/deduct.pass.cpp libcxx/trunk/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.fail.cpp libcxx/trunk/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp Modified: libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.fail.cpp?rev=334676=334675=334676=diff == --- libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.fail.cpp (original) +++ libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.fail.cpp Wed Jun 13 17:12:20 2018 @@ -19,7 +19,7 @@ int main() -{ +{ // Test the explicit deduction guides { // queue(Compare, Container, const Alloc); @@ -35,7 +35,7 @@ int main() } { -// priority_queue(Iter, Iter, Comp) +// priority_queue(Iter, Iter, Comp) // int is not an iterator std::priority_queue pri(15, 17, std::greater()); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'priority_queue'}} } Modified: libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp?rev=334676=334675=334676=diff == --- libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp (original) +++ libcxx/trunk/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp Wed Jun 13 17:12:20 2018 @@ -14,17 +14,17 @@ // template // priority_queue(Compare, Container) // -> priority_queue; -// +// // template::value_type>, // class Container = vector::value_type>> // priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) // -> priority_queue::value_type, Container, Compare>; -// +// // template // priority_queue(Compare, Container, Allocator) // -> priority_queue; - + #include #include @@ -41,7 +41,7 @@ struct A {}; int main() { - + // Test the explicit deduction guides { std::vector v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; @@ -56,7 +56,7 @@ int main() std::vector> v{10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; std::priority_queue pri(std::greater(), v, test_allocator(2)); // priority_queue(Compare, Container, Allocator) -static_assert(std::is_same_v>, std::greater>>, ""); assert(pri.size() == v.size()); assert(pri.top() == 10); Modified: libcxx/trunk/test/std/containers/container.adaptors/queue/queue.cons/deduct.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/container.adaptors/queue/queue.cons/deduct.fail.cpp?rev=334676=334675=334676=diff == --- libcxx/trunk/test/std/containers/container.adaptors/queue/queue.cons/deduct.fail.cpp (original) +++
r334674 - [www] Update cxx_status page for Rapperswil motions.
Author: rsmith Date: Wed Jun 13 17:05:28 2018 New Revision: 334674 URL: http://llvm.org/viewvc/llvm-project?rev=334674=rev Log: [www] Update cxx_status page for Rapperswil motions. Modified: cfe/trunk/www/cxx_status.html Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=334674=334673=334674=diff == --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Wed Jun 13 17:05:28 2018 @@ -844,10 +844,14 @@ as the draft C++2a standard evolves. Clang 6 - __VA_OPT__ for preprocessor comma elision + __VA_OPT__ for preprocessor comma elision http://wg21.link/p0306r4;>P0306R4 Clang 6 + +http://wg21.link/p1042r1;>P1042R1 +Partial + Designated initializers http://wg21.link/p0329r4;>P0329R4 @@ -883,13 +887,16 @@ as the draft C++2a standard evolves. No - Consistent comparison (operator=) + Consistent comparison (operator=) http://wg21.link/p0515r3;>P0515R3 - Partial + Partial http://wg21.link/p0905r1;>P0905R1 + +http://wg21.link/p1120r0;>P1120R0 + Access checking on specializations http://wg21.link/p0692r1;>P0692R1 @@ -926,6 +933,42 @@ as the draft C++2a standard evolves. http://wg21.link/p0780r2;>P0780R2 No + + + Class types as non-type template parameters + http://wg21.link/p0732r2;>P0732R2 + No + + + Destroying operator delete + http://wg21.link/p0722r3;>P0722R3 + Clang 6 + + + Virtual function calls in constant expressions + http://wg21.link/p1064r0;>P1064R0 + No + + + Prohibit aggregates with user-declared constructors + http://wg21.link/p1008r1;>P1008R1 + No + + + Contracts + http://wg21.link/p0542r5;>P0542R5 + No + + + Feature test macros + http://wg21.link/p0941r2;>P0941R2 + (see below) + + + explicit(bool) + http://wg21.link/p0892r2;>P0892R2 + No + @@ -958,7 +1001,7 @@ and library features that are not part o Compiler flag Available in Clang? - + SD-6: SG10 feature test recommendations http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations;>SD-6 N/A ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r334673 - Driver: De-duplicate some code. NFCI.
Author: pcc Date: Wed Jun 13 17:03:41 2018 New Revision: 334673 URL: http://llvm.org/viewvc/llvm-project?rev=334673=rev Log: Driver: De-duplicate some code. NFCI. Modified: cfe/trunk/lib/Driver/ToolChains/Clang.cpp Modified: cfe/trunk/lib/Driver/ToolChains/Clang.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/Clang.cpp?rev=334673=334672=334673=diff == --- cfe/trunk/lib/Driver/ToolChains/Clang.cpp (original) +++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp Wed Jun 13 17:03:41 2018 @@ -3501,8 +3501,7 @@ void Clang::ConstructJob(Compilation , Args.hasArg(options::OPT_dA)) CmdArgs.push_back("-masm-verbose"); - if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as, -IsIntegratedAssemblerDefault)) + if (!getToolChain().useIntegratedAs()) CmdArgs.push_back("-no-integrated-as"); if (Args.hasArg(options::OPT_fdebug_pass_structure)) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47567: Implement CFI for indirect calls via a member function pointer.
pcc updated this revision to Diff 151272. pcc added a comment. - Add some more documentation to ControlFlowIntegrity.rst https://reviews.llvm.org/D47567 Files: clang/docs/ControlFlowIntegrity.rst clang/docs/LTOVisibility.rst clang/include/clang/Basic/Sanitizers.def clang/lib/CodeGen/CGClass.cpp clang/lib/CodeGen/CGVTables.cpp clang/lib/CodeGen/CodeGenFunction.h clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenModule.h clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/SanitizerArgs.cpp clang/lib/Driver/ToolChains/MSVC.cpp clang/test/CodeGenCXX/cfi-mfcall-incomplete.cpp clang/test/CodeGenCXX/cfi-mfcall.cpp clang/test/CodeGenCXX/type-metadata.cpp clang/test/Driver/fsanitize.c compiler-rt/lib/ubsan/ubsan_handlers.cc compiler-rt/lib/ubsan/ubsan_handlers.h compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc compiler-rt/test/cfi/mfcall.cpp Index: compiler-rt/test/cfi/mfcall.cpp === --- /dev/null +++ compiler-rt/test/cfi/mfcall.cpp @@ -0,0 +1,94 @@ +// RUN: %clangxx_cfi -o %t %s +// RUN: %expect_crash %run %t a +// RUN: %expect_crash %run %t b +// RUN: %expect_crash %run %t c +// RUN: %expect_crash %run %t d +// RUN: %expect_crash %run %t e +// RUN: %run %t f +// RUN: %run %t g + +// RUN: %clangxx_cfi_diag -o %t2 %s +// RUN: %run %t2 a 2>&1 | FileCheck --check-prefix=A %s +// RUN: %run %t2 b 2>&1 | FileCheck --check-prefix=B %s +// RUN: %run %t2 c 2>&1 | FileCheck --check-prefix=C %s +// RUN: %run %t2 d 2>&1 | FileCheck --check-prefix=D %s +// RUN: %run %t2 e 2>&1 | FileCheck --check-prefix=E %s + +#include +#include + +struct SBase1 { + void b1() {} +}; + +struct SBase2 { + void b2() {} +}; + +struct S : SBase1, SBase2 { + void f1() {} + int f2() { return 1; } + virtual void g1() {} + virtual int g2() { return 1; } + virtual int g3() { return 1; } +}; + +struct T { + void f1() {} + int f2() { return 2; } + virtual void g1() {} + virtual int g2() { return 2; } + virtual void g3() {} +}; + +typedef void (S::*S_void)(); + +typedef int (S::*S_int)(); +typedef int (T::*T_int)(); + +template +To bitcast(From f) { + assert(sizeof(To) == sizeof(From)); + To t; + memcpy(, , sizeof(f)); + return t; +} + +int main(int argc, char **argv) { + S s; + T t; + + switch (argv[1][0]) { +case 'a': + // A: runtime error: control flow integrity check for type 'int (S::*)()' failed during non-virtual member function call + // A: note: S::f1() defined here + (s.*bitcast(::f1))(); + break; +case 'b': + // B: runtime error: control flow integrity check for type 'int (T::*)()' failed during non-virtual member function call + // B: note: S::f2() defined here + (t.*bitcast(::f2))(); + break; +case 'c': + // C: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual member function call + // C: note: vtable is of type 'S' + (s.*bitcast(::g1))(); + break; +case 'd': + // D: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual member function call + // D: note: vtable is of type 'T' + (reinterpret_cast(t).*::g2)(); + break; +case 'e': + // E: runtime error: control flow integrity check for type 'void (S::*)()' failed during virtual member function call + // E: note: vtable is of type 'S' + (s.*bitcast(::g3))(); + break; +case 'f': + (s.*::b1)(); + break; +case 'g': + (s.*::b2)(); + break; + } +} Index: compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc === --- compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc +++ compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc @@ -122,7 +122,11 @@ case CFITCK_UnrelatedCast: CheckKindStr = "cast to unrelated type"; break; + case CFITCK_VMFCall: +CheckKindStr = "virtual member function call"; +break; case CFITCK_ICall: + case CFITCK_NVMFCall: Die(); } Index: compiler-rt/lib/ubsan/ubsan_handlers.h === --- compiler-rt/lib/ubsan/ubsan_handlers.h +++ compiler-rt/lib/ubsan/ubsan_handlers.h @@ -181,6 +181,8 @@ CFITCK_DerivedCast, CFITCK_UnrelatedCast, CFITCK_ICall, + CFITCK_NVMFCall, + CFITCK_VMFCall, }; struct CFICheckFailData { Index: compiler-rt/lib/ubsan/ubsan_handlers.cc === --- compiler-rt/lib/ubsan/ubsan_handlers.cc +++ compiler-rt/lib/ubsan/ubsan_handlers.cc @@ -630,7 +630,7 @@ static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function, ReportOptions Opts) { - if (Data->CheckKind != CFITCK_ICall) + if (Data->CheckKind != CFITCK_ICall && Data->CheckKind != CFITCK_NVMFCall) Die(); SourceLocation Loc = Data->Loc.acquire(); @@ -641,9 +641,12 @@ ScopedReport R(Opts, Loc, ET);
r334671 - docs: Add a missing LTO visibility reference.
Author: pcc Date: Wed Jun 13 16:21:02 2018 New Revision: 334671 URL: http://llvm.org/viewvc/llvm-project?rev=334671=rev Log: docs: Add a missing LTO visibility reference. Modified: cfe/trunk/docs/ControlFlowIntegrity.rst Modified: cfe/trunk/docs/ControlFlowIntegrity.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ControlFlowIntegrity.rst?rev=334671=334670=334671=diff == --- cfe/trunk/docs/ControlFlowIntegrity.rst (original) +++ cfe/trunk/docs/ControlFlowIntegrity.rst Wed Jun 13 16:21:02 2018 @@ -104,10 +104,11 @@ dynamic type; that is, the dynamic type derived class of the static type of the object used to make the call. This CFI scheme can be enabled on its own using ``-fsanitize=cfi-vcall``. -For this scheme to work, all translation units containing the definition of -a virtual member function (whether inline or not), other than members of -:ref:`blacklisted ` types, must be compiled with ``-flto`` -or ``-flto=thin`` enabled and be statically linked into the program. +For this scheme to work, all translation units containing the definition +of a virtual member function (whether inline or not), other than members +of :ref:`blacklisted ` types or types with public :doc:`LTO +visibility `, must be compiled with ``-flto`` or ``-flto=thin`` +enabled and be statically linked into the program. Performance --- ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r334669 - docs: Correct some misstatements in the control flow integrity docs.
Author: pcc Date: Wed Jun 13 16:18:26 2018 New Revision: 334669 URL: http://llvm.org/viewvc/llvm-project?rev=334669=rev Log: docs: Correct some misstatements in the control flow integrity docs. These were true at one point but haven't been true for a long time. Modified: cfe/trunk/docs/ControlFlowIntegrity.rst Modified: cfe/trunk/docs/ControlFlowIntegrity.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ControlFlowIntegrity.rst?rev=334669=334668=334669=diff == --- cfe/trunk/docs/ControlFlowIntegrity.rst (original) +++ cfe/trunk/docs/ControlFlowIntegrity.rst Wed Jun 13 16:18:26 2018 @@ -104,10 +104,10 @@ dynamic type; that is, the dynamic type derived class of the static type of the object used to make the call. This CFI scheme can be enabled on its own using ``-fsanitize=cfi-vcall``. -For this scheme to work, all translation units containing the definition -of a virtual member function (whether inline or not), other than members -of :ref:`blacklisted ` types, must be compiled with -``-fsanitize=cfi-vcall`` enabled and be statically linked into the program. +For this scheme to work, all translation units containing the definition of +a virtual member function (whether inline or not), other than members of +:ref:`blacklisted ` types, must be compiled with ``-flto`` +or ``-flto=thin`` enabled and be statically linked into the program. Performance --- @@ -152,9 +152,9 @@ functions may be :ref:`blacklisted ` types, must be compiled with -``-fsanitize=cfi-derived-cast`` or ``-fsanitize=cfi-unrelated-cast`` enabled -and be statically linked into the program. +of :ref:`blacklisted ` types or types with public :doc:`LTO +visibility `, must be compiled with ``-flto`` or ``-flto=thin`` +enabled and be statically linked into the program. Non-Virtual Member Function Call Checking = @@ -168,8 +168,9 @@ polymorphic class type. This CFI scheme For this scheme to work, all translation units containing the definition of a virtual member function (whether inline or not), other than members -of :ref:`blacklisted ` types, must be compiled with -``-fsanitize=cfi-nvcall`` enabled and be statically linked into the program. +of :ref:`blacklisted ` types or types with public :doc:`LTO +visibility `, must be compiled with ``-flto`` or ``-flto=thin`` +enabled and be statically linked into the program. .. _cfi-strictness: ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48106: implemented proto to llvm
morehouse added a comment. In https://reviews.llvm.org/D48106#1131625, @emmettneyman wrote: > I wanted to implement the proto_to_llvm converter before the fuzz target. The fuzz target should make testing your converter way easier. I'd recommend adding it to this patch so that you're less likely to need a bug-fixing patch later. Comment at: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp:32 +// Counter variable to generate new LLVM IR variable names and wrapper function +int ctr = 0; +std::string get_var() { You can hide this as a static int inside `get_var`. Comment at: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp:46 + + "store i32 " + val + ", i32* " + alloca_var + "\n" + + load_var + " = load i32, i32* " + alloca_var + "\n"; + return std::make_pair(insns, load_var); What's the point of storing then loading the value? Can you just return `val`? Comment at: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp:49 +} +std::pair VarRefToString(const VarRef ) { + std::string arr; Returning a pair can be confusing (which element is which?). I'd suggest passing `os` to these functions, writing the instructions to `os`, and then returning just the result variable. Comment at: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp:120 +op = "add"; +break; + } If all these cases are the same, we can simplify the code to ``` case BinaryOp::EQ: case BinaryOp::NE: ... op = "add"; break; ``` Comment at: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp:129 +} +std::string AssignmentStatementToString(const AssignmentStatement ) { + std::pair ref = VarRefToString(x.varref()); If `AssignmentStatementToString` has no extra return value, I think its more concise to just keep the `operator<<` overload. (Same for below functions) Repository: rC Clang https://reviews.llvm.org/D48106 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48027: [analyzer] Improve `CallDescription` to handle c++ method.
NoQ added inline comments. Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:32 check::PostCall> { - CallDescription CStrFn; + const llvm::SmallVector CStrFnFamily = { +{"std::basic_string::c_str"}, {"std::basic_string::c_str"}, xazax.hun wrote: > I am not sure if this is the right solution in case of this check. We should > track `c_str` calls regardless of what the template parameter is, so > supporting any instantiation of `basic_string` is desired. This might not be > the case, however, for other checks. > > If we think it is more likely we do not care about the template arguments, > maybe a separate API could be used, where we pass the qualified name of the > class separately without the template arguments. > Alternatively, we could use matches name so the users could use regexps. > > At this point I also wonder what isCalled API gives us compared to matchers? > Maybe it is more convenient to use than calling a `match`. Also, isCalled API > has an IdentifierInfo cached which could be used for relatively efficient > checks. > > @NoQ what do you think? > > I agree that it's better to match the chain of classes and namespaces (in as much detail as the user cares to provide) and discard template parameters. For example, i wish that a `CallDescription` that's defined as `{"std", "basic_string", "c_str"}` would be able to match both `std::string::c_str()` and `std::__1::string::c_str()`. Repository: rC Clang https://reviews.llvm.org/D48027 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48098: clang-format-diff: Switch to python3 by default, support python 2.7
MarcoFalke updated this revision to Diff 151260. MarcoFalke edited the summary of this revision. https://reviews.llvm.org/D48098 Files: tools/clang-format/clang-format-diff.py Index: tools/clang-format/clang-format-diff.py === --- tools/clang-format/clang-format-diff.py +++ tools/clang-format/clang-format-diff.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # #===- clang-format-diff.py - ClangFormat Diff Reformatter *- python -*--===# # @@ -25,10 +25,12 @@ import argparse import difflib import re -import string import subprocess -import StringIO import sys +try: + from StringIO import StringIO +except ImportError: + from io import StringIO def main(): @@ -84,14 +86,14 @@ line_count = int(match.group(3)) if line_count == 0: continue - end_line = start_line + line_count - 1; + end_line = start_line + line_count - 1 lines_by_file.setdefault(filename, []).extend( ['-lines', str(start_line) + ':' + str(end_line)]) # Reformat files containing changes in place. - for filename, lines in lines_by_file.iteritems(): + for filename, lines in lines_by_file.items(): if args.i and args.verbose: - print 'Formatting', filename + print('Formatting {}'.format(filename)) command = [args.binary, filename] if args.i: command.append('-i') @@ -100,20 +102,23 @@ command.extend(lines) if args.style: command.extend(['-style', args.style]) -p = subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=None, stdin=subprocess.PIPE) +p = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=None, + stdin=subprocess.PIPE, + universal_newlines=True) stdout, stderr = p.communicate() if p.returncode != 0: - sys.exit(p.returncode); + sys.exit(p.returncode) if not args.i: with open(filename) as f: code = f.readlines() - formatted_code = StringIO.StringIO(stdout).readlines() + formatted_code = StringIO(stdout).readlines() diff = difflib.unified_diff(code, formatted_code, filename, filename, '(before formatting)', '(after formatting)') - diff_string = string.join(diff, '') + diff_string = ''.join(diff) if len(diff_string) > 0: sys.stdout.write(diff_string) Index: tools/clang-format/clang-format-diff.py === --- tools/clang-format/clang-format-diff.py +++ tools/clang-format/clang-format-diff.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # #===- clang-format-diff.py - ClangFormat Diff Reformatter *- python -*--===# # @@ -25,10 +25,12 @@ import argparse import difflib import re -import string import subprocess -import StringIO import sys +try: + from StringIO import StringIO +except ImportError: + from io import StringIO def main(): @@ -84,14 +86,14 @@ line_count = int(match.group(3)) if line_count == 0: continue - end_line = start_line + line_count - 1; + end_line = start_line + line_count - 1 lines_by_file.setdefault(filename, []).extend( ['-lines', str(start_line) + ':' + str(end_line)]) # Reformat files containing changes in place. - for filename, lines in lines_by_file.iteritems(): + for filename, lines in lines_by_file.items(): if args.i and args.verbose: - print 'Formatting', filename + print('Formatting {}'.format(filename)) command = [args.binary, filename] if args.i: command.append('-i') @@ -100,20 +102,23 @@ command.extend(lines) if args.style: command.extend(['-style', args.style]) -p = subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=None, stdin=subprocess.PIPE) +p = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=None, + stdin=subprocess.PIPE, + universal_newlines=True) stdout, stderr = p.communicate() if p.returncode != 0: - sys.exit(p.returncode); + sys.exit(p.returncode) if not args.i: with open(filename) as f: code = f.readlines() - formatted_code = StringIO.StringIO(stdout).readlines() + formatted_code = StringIO(stdout).readlines() diff = difflib.unified_diff(code, formatted_code, filename, filename, '(before formatting)', '(after formatting)') - diff_string = string.join(diff, '') + diff_string = ''.join(diff) if len(diff_string) > 0: sys.stdout.write(diff_string) ___
[PATCH] D47554: [analyzer] Check for dead/impossible status checks
NoQ added a comment. For now the tests that i proposed may in fact accidentally work because as far as i understand you're updating the "variable contains a value returned by operator new" flag when you encounter assignment operators. The real problems will arise when the order of the assignments in the AST doesn't correspond to the order of assignments during program execution. So one more test i'd like to have is: int *m = new int; while (true) { if (m == nullptr) { ... } // no-warning m = nullptr; } Repository: rC Clang https://reviews.llvm.org/D47554 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47554: [analyzer] Check for dead/impossible status checks
NoQ added a comment. Thanks for adding me! Hmm, i think a matcher-based solution would be pretty limited. This is definitely your typical all-path data-flow problem because you want to make sure that you're looking at the //last// assignment to the variable. For example: int *m = new int; m = nullptr; if (m == nullptr) { ... } // no-warning but int *m = nullptr; m = new int; if (m == nullptr) { ... } // expected-warning{{}} You might be able to fix false positives by adding a condition that the variable is not re-assigned within the function (with the help of assignment operator or due to taking a non-constant reference to it, etc). But you'll end up with a checker that finds a lot less bugs than a full-featured data flow analysis could have found. There's a canonical implementation of "the variable is not modified" check via ASTMatchers in `LoopUnrolling.cpp`. If you'll ever want to find a full-featured data flow check, i'm not sure but you might be able to re-use `LiveVariables` analysis (the non-`Relaxed` one) to find the last assignment, and in this case you won't have to write data flow analysis yourself. `DeadStores` checker has an example of that. Repository: rC Clang https://reviews.llvm.org/D47554 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48098: clang-format-diff: Switch to python3 by default, support python 2.7
MarcoFalke added a comment. > why is this switch necessary? It is not necessary, but would be nice if the script run on python3 as well (as opposed to only python2, which is going to be deprecated https://pythonclock.org/) > what's expected to be supported with it? I'd assume python2.7 (which is the only supported python2) and everything from python3.4 and upward. > how do I test it? The clang-format-diff.py is a wrapper around clang-format, to format only a diff. You can get any diff, e.g. the last ten commits to the master branch: git diff HEAD~10 -U0 | python2 ./tools/clang-format/clang-format-diff.py (You might have to pass `-p1`) Then test that the following options work with both python2 and python3: -i -v # flags -regex # could be -regex '.*\.h' -iregex # could be -iregex '.*\.H' https://reviews.llvm.org/D48098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D42043: c-index: CXString: fix MSAN read-past-end bug
vitalybuka added a comment. Is this stale? Repository: rC Clang https://reviews.llvm.org/D42043 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48036: [CUDA] Make min/max shims host+device.
jlebar added a comment. In https://reviews.llvm.org/D48036#1131279, @tra wrote: > Ack. Patches sent (see dependency chain in phab). https://reviews.llvm.org/D48036 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48152: [CUDA] Add tests that, in C++14 mode, min/max are constexpr.
jlebar created this revision. jlebar added reviewers: rsmith, tra. Herald added a subscriber: llvm-commits. Repository: rT test-suite https://reviews.llvm.org/D48152 Files: External/CUDA/algorithm.cu Index: External/CUDA/algorithm.cu === --- External/CUDA/algorithm.cu +++ External/CUDA/algorithm.cu @@ -42,6 +42,8 @@ assert(std::minmax(1, 0).second == 1); assert(std::minmax({0, 10, -10, 100}, std::less()).first == -10); assert(std::minmax({0, 10, -10, 100}, std::less()).second == 100); + constexpr auto min = std::min(1, 2); + constexpr auto max = std::max(1, 2); #endif } @@ -56,6 +58,8 @@ assert(std::minmax(1, 0).second == 1); assert(std::minmax({0, 10, -10, 100}, std::less()).first == -10); assert(std::minmax({0, 10, -10, 100}, std::less()).second == 100); + constexpr auto min = std::min(1, 2); + constexpr auto max = std::max(1, 2); #endif } Index: External/CUDA/algorithm.cu === --- External/CUDA/algorithm.cu +++ External/CUDA/algorithm.cu @@ -42,6 +42,8 @@ assert(std::minmax(1, 0).second == 1); assert(std::minmax({0, 10, -10, 100}, std::less()).first == -10); assert(std::minmax({0, 10, -10, 100}, std::less()).second == 100); + constexpr auto min = std::min(1, 2); + constexpr auto max = std::max(1, 2); #endif } @@ -56,6 +58,8 @@ assert(std::minmax(1, 0).second == 1); assert(std::minmax({0, 10, -10, 100}, std::less()).first == -10); assert(std::minmax({0, 10, -10, 100}, std::less()).second == 100); + constexpr auto min = std::min(1, 2); + constexpr auto max = std::max(1, 2); #endif } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48151: [CUDA] Make __host__/__device__ min/max overloads constexpr in C++14.
jlebar created this revision. jlebar added reviewers: rsmith, tra. Herald added a subscriber: sanjoy. Tests in a separate change to the test-suite. https://reviews.llvm.org/D48151 Files: clang/lib/Headers/cuda_wrappers/algorithm Index: clang/lib/Headers/cuda_wrappers/algorithm === --- clang/lib/Headers/cuda_wrappers/algorithm +++ clang/lib/Headers/cuda_wrappers/algorithm @@ -67,34 +67,43 @@ #endif #endif +#pragma push_macro("_CPP14_CONSTEXPR") +#if __cplusplus >= 201402L +#define _CPP14_CONSTEXPR constexpr +#else +#define _CPP14_CONSTEXPR +#endif + template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & max(const __T &__a, const __T &__b, __Cmp __cmp) { return __cmp(__a, __b) ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & max(const __T &__a, const __T &__b) { return __a < __b ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & min(const __T &__a, const __T &__b, __Cmp __cmp) { return __cmp(__b, __a) ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & min(const __T &__a, const __T &__b) { return __a < __b ? __a : __b; } +#pragma pop_macro("_CPP14_CONSTEXPR") + #ifdef _LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD #else Index: clang/lib/Headers/cuda_wrappers/algorithm === --- clang/lib/Headers/cuda_wrappers/algorithm +++ clang/lib/Headers/cuda_wrappers/algorithm @@ -67,34 +67,43 @@ #endif #endif +#pragma push_macro("_CPP14_CONSTEXPR") +#if __cplusplus >= 201402L +#define _CPP14_CONSTEXPR constexpr +#else +#define _CPP14_CONSTEXPR +#endif + template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & max(const __T &__a, const __T &__b, __Cmp __cmp) { return __cmp(__a, __b) ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & max(const __T &__a, const __T &__b) { return __a < __b ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & min(const __T &__a, const __T &__b, __Cmp __cmp) { return __cmp(__b, __a) ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & min(const __T &__a, const __T &__b) { return __a < __b ? __a : __b; } +#pragma pop_macro("_CPP14_CONSTEXPR") + #ifdef _LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD #else ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48100: Append new attributes to the end of an AttributeList.
Meinersbur marked 4 inline comments as done. Meinersbur added inline comments. Comment at: lib/AST/ItaniumMangle.cpp:710-711 Out << "Ua9enable_ifI"; // FIXME: specific_attr_iterator iterates in reverse order. Fix that and use // it here. +for (AttrVec::const_iterator I = FD->getAttrs().begin(), Will remove this FIXME in the next update. Repository: rC Clang https://reviews.llvm.org/D48100 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38680: [libunwind] Fix handling of DW_CFA_GNU_args_size
rnk added a comment. In https://reviews.llvm.org/D38680#1123018, @joerg wrote: > After a careful review of newer GCC / libgcc and the assembler annotations > from LLVM, I have come to the following conclusions: > > (1) The semantics have been somewhat changed by GCC in recent years. There is > no actual specification, so we have to go by what behavior actually makes > sense. > (2) The primary motivation is still that the DW_CFA_GNU_args_size is a > call-site specific annotation. It is expected to be applied when the IP is > moved by the personality routine to compensate for the call site specific > (temporary) adjustment. Right. > (3) It is not clear with plain unw_set_ip outside the scope of the Itanium EH > handling should have this behavior, so it might need to be split into an > internal routine. I don't know enough about this code to really respond to this. > (4) LLVM does not produce correct CFA annotation for stdcall and similar > cases where the callee removes additional stack space. Here's what we generate for that case today: https://godbolt.org/g/33cNJy The important part is: .cfi_escape 0x2e, 0x0c pushl $3 .cfi_adjust_cfa_offset 4 pushl $2 .cfi_adjust_cfa_offset 4 pushl $1 .cfi_adjust_cfa_offset 4 calll __Z13may_throw_stdiii@12 .cfi_adjust_cfa_offset -12 Are you saying that the runtime will calculate the wrong CFA because it will include the `.cfi_adjust_cfa_offset -12`? As in, adding a nop after the call would fix the glitch? If so, I think the right thing to do would be to fix libunwind to use return_address - 1 when unwinding. https://reviews.llvm.org/D38680 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47401: [X86] Rewrite the max and min reduction intrinsics to make better use of other functions and to reduce width to 256 and 128 bits were possible.
craig.topper added a comment. Ping Repository: rL LLVM https://reviews.llvm.org/D47401 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48134: [CodeGen] make nan builtins pure rather than const (PR37778)
spatel added a comment. In https://reviews.llvm.org/D48134#1131626, @rsmith wrote: > Can we mark these as `argmemonly`? I wasn't aware of that one, but it sounds accurate for nan() and friends: argmemonly This attribute indicates that the only memory accesses inside function are loads and stores from objects pointed to by its pointer-typed arguments, with arbitrary offsets. Or in other words, all memory operations in the function can refer to memory only using pointers based on its function arguments. Note that argmemonly can be used together with readonly attribute in order to specify that function reads only from its arguments. But as Roman noted, we're going to have to update the list of possibilities to include "NoAliasAttr"? And might need to adjust the logic where that gets mapped to the LLVM attr. Repository: rL LLVM https://reviews.llvm.org/D48134 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45679: [clang-tidy] Add ExprMutationAnalyzer, that analyzes whether an expression is mutated within a statement.
shuaiwang added a comment. In https://reviews.llvm.org/D45679#1131115, @aaron.ballman wrote: > I had to revert due to failing tests. The revert was done in r334606 and this > is an example of a failing bot: > http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/builds/31500 Apparently I can't include in unit test cases (somehow that works on my machine :p) Changed to just forward declare std::type_info instead. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D45679 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45679: [clang-tidy] Add ExprMutationAnalyzer, that analyzes whether an expression is mutated within a statement.
shuaiwang updated this revision to Diff 151245. shuaiwang added a comment. Add include for std::isspace() (thanks aaron.ballman!) Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D45679 Files: clang-tidy/utils/CMakeLists.txt clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tidy/utils/ExprMutationAnalyzer.h unittests/clang-tidy/CMakeLists.txt unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Index: unittests/clang-tidy/ExprMutationAnalyzerTest.cpp === --- /dev/null +++ unittests/clang-tidy/ExprMutationAnalyzerTest.cpp @@ -0,0 +1,609 @@ +//===-- ExprMutationAnalyzerTest.cpp - clang-tidy -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "../clang-tidy/utils/ExprMutationAnalyzer.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Tooling/Tooling.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include + +namespace clang { +namespace tidy { +namespace test { + +using namespace clang::ast_matchers; +using ::testing::ElementsAre; +using ::testing::IsEmpty; +using ::testing::ResultOf; +using ::testing::StartsWith; +using ::testing::Values; + +namespace { + +using ExprMatcher = internal::Matcher; +using StmtMatcher = internal::Matcher; + +ExprMatcher declRefTo(StringRef Name) { + return declRefExpr(to(namedDecl(hasName(Name; +} + +StmtMatcher withEnclosingCompound(ExprMatcher Matcher) { + return expr(Matcher, hasAncestor(compoundStmt().bind("stmt"))).bind("expr"); +} + +bool isMutated(const SmallVectorImpl , ASTUnit *AST) { + const auto *const S = selectFirst("stmt", Results); + const auto *const E = selectFirst("expr", Results); + return utils::ExprMutationAnalyzer(S, >getASTContext()).isMutated(E); +} + +SmallVector +mutatedBy(const SmallVectorImpl , ASTUnit *AST) { + const auto *const S = selectFirst("stmt", Results); + SmallVector Chain; + utils::ExprMutationAnalyzer Analyzer(S, >getASTContext()); + for (const auto *E = selectFirst("expr", Results); E != nullptr;) { +const Stmt *By = Analyzer.findMutation(E); +std::string buffer; +llvm::raw_string_ostream stream(buffer); +By->printPretty(stream, nullptr, AST->getASTContext().getPrintingPolicy()); +Chain.push_back(StringRef(stream.str()).trim().str()); +E = dyn_cast(By); + } + return Chain; +} + +std::string removeSpace(std::string s) { + s.erase(std::remove_if(s.begin(), s.end(), + [](char c) { return std::isspace(c); }), + s.end()); + return s; +} + +} // namespace + +TEST(ExprMutationAnalyzerTest, Trivial) { + const auto AST = tooling::buildASTFromCode("void f() { int x; x; }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); +} + +class AssignmentTest : public ::testing::TestWithParam {}; + +TEST_P(AssignmentTest, AssignmentModifies) { + const std::string ModExpr = "x " + GetParam() + " 10"; + const auto AST = + tooling::buildASTFromCode("void f() { int x; " + ModExpr + "; }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr)); +} + +INSTANTIATE_TEST_CASE_P(AllAssignmentOperators, AssignmentTest, +Values("=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", + "^=", "<<=", ">>="), ); + +class IncDecTest : public ::testing::TestWithParam {}; + +TEST_P(IncDecTest, IncDecModifies) { + const std::string ModExpr = GetParam(); + const auto AST = + tooling::buildASTFromCode("void f() { int x; " + ModExpr + "; }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr)); +} + +INSTANTIATE_TEST_CASE_P(AllIncDecOperators, IncDecTest, +Values("++x", "--x", "x++", "x--"), ); + +TEST(ExprMutationAnalyzerTest, NonConstMemberFunc) { + const auto AST = tooling::buildASTFromCode( + "void f() { struct Foo { void mf(); }; Foo x; x.mf(); }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); +} + +TEST(ExprMutationAnalyzerTest, ConstMemberFunc) { + const auto AST = tooling::buildASTFromCode( + "void f() { struct Foo { void mf() const; }; Foo x; x.mf(); }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, NonConstOperator) { +
[PATCH] D48134: [CodeGen] make nan builtins pure rather than const (PR37778)
lebedev.ri added a comment. In https://reviews.llvm.org/D48134#1131626, @rsmith wrote: > Can we mark these as `argmemonly`? Header comment in `include/clang/Basic/Builtins.def` does not list that as a possibility. Repository: rL LLVM https://reviews.llvm.org/D48134 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45679: [clang-tidy] Add ExprMutationAnalyzer, that analyzes whether an expression is mutated within a statement.
shuaiwang updated this revision to Diff 151244. shuaiwang added a comment. Don't include in unit tests, should fix the test failures. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D45679 Files: clang-tidy/utils/CMakeLists.txt clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tidy/utils/ExprMutationAnalyzer.h unittests/clang-tidy/CMakeLists.txt unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Index: unittests/clang-tidy/ExprMutationAnalyzerTest.cpp === --- /dev/null +++ unittests/clang-tidy/ExprMutationAnalyzerTest.cpp @@ -0,0 +1,608 @@ +//===-- ExprMutationAnalyzerTest.cpp - clang-tidy -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "../clang-tidy/utils/ExprMutationAnalyzer.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Tooling/Tooling.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace tidy { +namespace test { + +using namespace clang::ast_matchers; +using ::testing::ElementsAre; +using ::testing::IsEmpty; +using ::testing::ResultOf; +using ::testing::StartsWith; +using ::testing::Values; + +namespace { + +using ExprMatcher = internal::Matcher; +using StmtMatcher = internal::Matcher; + +ExprMatcher declRefTo(StringRef Name) { + return declRefExpr(to(namedDecl(hasName(Name; +} + +StmtMatcher withEnclosingCompound(ExprMatcher Matcher) { + return expr(Matcher, hasAncestor(compoundStmt().bind("stmt"))).bind("expr"); +} + +bool isMutated(const SmallVectorImpl , ASTUnit *AST) { + const auto *const S = selectFirst("stmt", Results); + const auto *const E = selectFirst("expr", Results); + return utils::ExprMutationAnalyzer(S, >getASTContext()).isMutated(E); +} + +SmallVector +mutatedBy(const SmallVectorImpl , ASTUnit *AST) { + const auto *const S = selectFirst("stmt", Results); + SmallVector Chain; + utils::ExprMutationAnalyzer Analyzer(S, >getASTContext()); + for (const auto *E = selectFirst("expr", Results); E != nullptr;) { +const Stmt *By = Analyzer.findMutation(E); +std::string buffer; +llvm::raw_string_ostream stream(buffer); +By->printPretty(stream, nullptr, AST->getASTContext().getPrintingPolicy()); +Chain.push_back(StringRef(stream.str()).trim().str()); +E = dyn_cast(By); + } + return Chain; +} + +std::string removeSpace(std::string s) { + s.erase(std::remove_if(s.begin(), s.end(), + [](char c) { return std::isspace(c); }), + s.end()); + return s; +} + +} // namespace + +TEST(ExprMutationAnalyzerTest, Trivial) { + const auto AST = tooling::buildASTFromCode("void f() { int x; x; }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); +} + +class AssignmentTest : public ::testing::TestWithParam {}; + +TEST_P(AssignmentTest, AssignmentModifies) { + const std::string ModExpr = "x " + GetParam() + " 10"; + const auto AST = + tooling::buildASTFromCode("void f() { int x; " + ModExpr + "; }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr)); +} + +INSTANTIATE_TEST_CASE_P(AllAssignmentOperators, AssignmentTest, +Values("=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", + "^=", "<<=", ">>="), ); + +class IncDecTest : public ::testing::TestWithParam {}; + +TEST_P(IncDecTest, IncDecModifies) { + const std::string ModExpr = GetParam(); + const auto AST = + tooling::buildASTFromCode("void f() { int x; " + ModExpr + "; }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr)); +} + +INSTANTIATE_TEST_CASE_P(AllIncDecOperators, IncDecTest, +Values("++x", "--x", "x++", "x--"), ); + +TEST(ExprMutationAnalyzerTest, NonConstMemberFunc) { + const auto AST = tooling::buildASTFromCode( + "void f() { struct Foo { void mf(); }; Foo x; x.mf(); }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); +} + +TEST(ExprMutationAnalyzerTest, ConstMemberFunc) { + const auto AST = tooling::buildASTFromCode( + "void f() { struct Foo { void mf() const; }; Foo x; x.mf(); }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, NonConstOperator) { + const
r334652 - Simplify test from r334650
Author: erichkeane Date: Wed Jun 13 13:47:12 2018 New Revision: 334652 URL: http://llvm.org/viewvc/llvm-project?rev=334652=rev Log: Simplify test from r334650 No reason to have the 'bool' as an intermediary value, simply use the fact that curley braces enforce eval order. Modified: cfe/trunk/test/SemaCXX/builtins-overflow.cpp Modified: cfe/trunk/test/SemaCXX/builtins-overflow.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/builtins-overflow.cpp?rev=334652=334651=334652=diff == --- cfe/trunk/test/SemaCXX/builtins-overflow.cpp (original) +++ cfe/trunk/test/SemaCXX/builtins-overflow.cpp Wed Jun 13 13:47:12 2018 @@ -29,8 +29,7 @@ struct Result { template constexpr Result add(LHS &, RHS &) { RET sum{}; - bool b = __builtin_add_overflow(lhs, rhs, ); - return {b, sum}; + return {__builtin_add_overflow(lhs, rhs, ), sum}; } static_assert(add(static_cast(120), static_cast(10)) == Result{false, 130}); @@ -45,8 +44,7 @@ static_assert(add(INT_MIN + 22, -23 template constexpr Result sub(LHS &, RHS &) { RET sum{}; - bool b = __builtin_sub_overflow(lhs, rhs, ); - return {b, sum}; + return {__builtin_sub_overflow(lhs, rhs, ), sum}; } static_assert(sub(static_cast(0),static_cast(1)) == Result{true, UCHAR_MAX}); @@ -60,8 +58,7 @@ static_assert(sub(INT_MIN + 22, 23) template constexpr Result mul(LHS &, RHS &) { RET sum{}; - bool b = __builtin_mul_overflow(lhs, rhs, ); - return {b, sum}; + return {__builtin_mul_overflow(lhs, rhs, ), sum}; } static_assert(mul(17,22) == Result{false, 374}); @@ -70,8 +67,7 @@ static_assert(mul(INT_MIN / 22, -23 constexpr Result sadd(int lhs, int rhs) { int sum{}; - bool b = __builtin_sadd_overflow(lhs, rhs, ); - return {b, sum}; + return {__builtin_sadd_overflow(lhs, rhs, ), sum}; } static_assert(sadd(17,22) == Result{false, 39}); @@ -80,8 +76,7 @@ static_assert(sadd(INT_MIN + 22, -23) == constexpr Result ssub(int lhs, int rhs) { int sum{}; - bool b = __builtin_ssub_overflow(lhs, rhs, ); - return {b, sum}; + return {__builtin_ssub_overflow(lhs, rhs, ), sum}; } static_assert(ssub(17,22) == Result{false, -5}); @@ -90,8 +85,7 @@ static_assert(ssub(INT_MIN + 22, 23) == constexpr Result smul(int lhs, int rhs) { int sum{}; - bool b = __builtin_smul_overflow(lhs, rhs, ); - return {b, sum}; + return {__builtin_smul_overflow(lhs, rhs, ), sum}; } static_assert(smul(17,22) == Result{false, 374}); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48040: Implement constexpr __builtin_*_overflow
This revision was automatically updated to reflect the committed changes. Closed by commit rL334650: Implement constexpr __builtin_*_overflow (authored by erichkeane, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D48040?vs=151151=151241#toc Repository: rL LLVM https://reviews.llvm.org/D48040 Files: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/SemaCXX/builtins-overflow.cpp Index: cfe/trunk/lib/AST/ExprConstant.cpp === --- cfe/trunk/lib/AST/ExprConstant.cpp +++ cfe/trunk/lib/AST/ExprConstant.cpp @@ -8155,6 +8155,124 @@ case Builtin::BIomp_is_initial_device: // We can decide statically which value the runtime would return if called. return Success(Info.getLangOpts().OpenMPIsDevice ? 0 : 1, E); + case Builtin::BI__builtin_add_overflow: + case Builtin::BI__builtin_sub_overflow: + case Builtin::BI__builtin_mul_overflow: + case Builtin::BI__builtin_sadd_overflow: + case Builtin::BI__builtin_uadd_overflow: + case Builtin::BI__builtin_uaddl_overflow: + case Builtin::BI__builtin_uaddll_overflow: + case Builtin::BI__builtin_usub_overflow: + case Builtin::BI__builtin_usubl_overflow: + case Builtin::BI__builtin_usubll_overflow: + case Builtin::BI__builtin_umul_overflow: + case Builtin::BI__builtin_umull_overflow: + case Builtin::BI__builtin_umulll_overflow: + case Builtin::BI__builtin_saddl_overflow: + case Builtin::BI__builtin_saddll_overflow: + case Builtin::BI__builtin_ssub_overflow: + case Builtin::BI__builtin_ssubl_overflow: + case Builtin::BI__builtin_ssubll_overflow: + case Builtin::BI__builtin_smul_overflow: + case Builtin::BI__builtin_smull_overflow: + case Builtin::BI__builtin_smulll_overflow: { +LValue ResultLValue; +APSInt LHS, RHS; + +QualType ResultType = E->getArg(2)->getType()->getPointeeType(); +if (!EvaluateInteger(E->getArg(0), LHS, Info) || +!EvaluateInteger(E->getArg(1), RHS, Info) || +!EvaluatePointer(E->getArg(2), ResultLValue, Info)) + return false; + +APSInt Result; +bool DidOverflow = false; + +// If the types don't have to match, enlarge all 3 to the largest of them. +if (BuiltinOp == Builtin::BI__builtin_add_overflow || +BuiltinOp == Builtin::BI__builtin_sub_overflow || +BuiltinOp == Builtin::BI__builtin_mul_overflow) { + bool IsSigned = LHS.isSigned() || RHS.isSigned() || + ResultType->isSignedIntegerOrEnumerationType(); + bool AllSigned = LHS.isSigned() && RHS.isSigned() && + ResultType->isSignedIntegerOrEnumerationType(); + uint64_t LHSSize = LHS.getBitWidth(); + uint64_t RHSSize = RHS.getBitWidth(); + uint64_t ResultSize = Info.Ctx.getTypeSize(ResultType); + uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize); + + // Add an additional bit if the signedness isn't uniformly agreed to. We + // could do this ONLY if there is a signed and an unsigned that both have + // MaxBits, but the code to check that is pretty nasty. The issue will be + // caught in the shrink-to-result later anyway. + if (IsSigned && !AllSigned) +++MaxBits; + + LHS = APSInt(IsSigned ? LHS.sextOrSelf(MaxBits) : LHS.zextOrSelf(MaxBits), + !IsSigned); + RHS = APSInt(IsSigned ? RHS.sextOrSelf(MaxBits) : RHS.zextOrSelf(MaxBits), + !IsSigned); + Result = APSInt(MaxBits, !IsSigned); +} + +// Find largest int. +switch (BuiltinOp) { +default: + llvm_unreachable("Invalid value for BuiltinOp"); +case Builtin::BI__builtin_add_overflow: +case Builtin::BI__builtin_sadd_overflow: +case Builtin::BI__builtin_saddl_overflow: +case Builtin::BI__builtin_saddll_overflow: +case Builtin::BI__builtin_uadd_overflow: +case Builtin::BI__builtin_uaddl_overflow: +case Builtin::BI__builtin_uaddll_overflow: + Result = LHS.isSigned() ? LHS.sadd_ov(RHS, DidOverflow) + : LHS.uadd_ov(RHS, DidOverflow); + break; +case Builtin::BI__builtin_sub_overflow: +case Builtin::BI__builtin_ssub_overflow: +case Builtin::BI__builtin_ssubl_overflow: +case Builtin::BI__builtin_ssubll_overflow: +case Builtin::BI__builtin_usub_overflow: +case Builtin::BI__builtin_usubl_overflow: +case Builtin::BI__builtin_usubll_overflow: + Result = LHS.isSigned() ? LHS.ssub_ov(RHS, DidOverflow) + : LHS.usub_ov(RHS, DidOverflow); + break; +case Builtin::BI__builtin_mul_overflow: +case Builtin::BI__builtin_smul_overflow: +case Builtin::BI__builtin_smull_overflow: +case Builtin::BI__builtin_smulll_overflow: +case Builtin::BI__builtin_umul_overflow: +case Builtin::BI__builtin_umull_overflow: +case Builtin::BI__builtin_umulll_overflow: + Result = LHS.isSigned() ? LHS.smul_ov(RHS, DidOverflow) +
r334650 - Implement constexpr __builtin_*_overflow
Author: erichkeane Date: Wed Jun 13 13:43:27 2018 New Revision: 334650 URL: http://llvm.org/viewvc/llvm-project?rev=334650=rev Log: Implement constexpr __builtin_*_overflow As requested here:https://bugs.llvm.org/show_bug.cgi?id=37633 permit the __builtin_*_overflow builtins in constexpr functions. Differential Revision: https://reviews.llvm.org/D48040 Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/SemaCXX/builtins-overflow.cpp Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=334650=334649=334650=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Jun 13 13:43:27 2018 @@ -8155,6 +8155,124 @@ bool IntExprEvaluator::VisitBuiltinCallE case Builtin::BIomp_is_initial_device: // We can decide statically which value the runtime would return if called. return Success(Info.getLangOpts().OpenMPIsDevice ? 0 : 1, E); + case Builtin::BI__builtin_add_overflow: + case Builtin::BI__builtin_sub_overflow: + case Builtin::BI__builtin_mul_overflow: + case Builtin::BI__builtin_sadd_overflow: + case Builtin::BI__builtin_uadd_overflow: + case Builtin::BI__builtin_uaddl_overflow: + case Builtin::BI__builtin_uaddll_overflow: + case Builtin::BI__builtin_usub_overflow: + case Builtin::BI__builtin_usubl_overflow: + case Builtin::BI__builtin_usubll_overflow: + case Builtin::BI__builtin_umul_overflow: + case Builtin::BI__builtin_umull_overflow: + case Builtin::BI__builtin_umulll_overflow: + case Builtin::BI__builtin_saddl_overflow: + case Builtin::BI__builtin_saddll_overflow: + case Builtin::BI__builtin_ssub_overflow: + case Builtin::BI__builtin_ssubl_overflow: + case Builtin::BI__builtin_ssubll_overflow: + case Builtin::BI__builtin_smul_overflow: + case Builtin::BI__builtin_smull_overflow: + case Builtin::BI__builtin_smulll_overflow: { +LValue ResultLValue; +APSInt LHS, RHS; + +QualType ResultType = E->getArg(2)->getType()->getPointeeType(); +if (!EvaluateInteger(E->getArg(0), LHS, Info) || +!EvaluateInteger(E->getArg(1), RHS, Info) || +!EvaluatePointer(E->getArg(2), ResultLValue, Info)) + return false; + +APSInt Result; +bool DidOverflow = false; + +// If the types don't have to match, enlarge all 3 to the largest of them. +if (BuiltinOp == Builtin::BI__builtin_add_overflow || +BuiltinOp == Builtin::BI__builtin_sub_overflow || +BuiltinOp == Builtin::BI__builtin_mul_overflow) { + bool IsSigned = LHS.isSigned() || RHS.isSigned() || + ResultType->isSignedIntegerOrEnumerationType(); + bool AllSigned = LHS.isSigned() && RHS.isSigned() && + ResultType->isSignedIntegerOrEnumerationType(); + uint64_t LHSSize = LHS.getBitWidth(); + uint64_t RHSSize = RHS.getBitWidth(); + uint64_t ResultSize = Info.Ctx.getTypeSize(ResultType); + uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize); + + // Add an additional bit if the signedness isn't uniformly agreed to. We + // could do this ONLY if there is a signed and an unsigned that both have + // MaxBits, but the code to check that is pretty nasty. The issue will be + // caught in the shrink-to-result later anyway. + if (IsSigned && !AllSigned) +++MaxBits; + + LHS = APSInt(IsSigned ? LHS.sextOrSelf(MaxBits) : LHS.zextOrSelf(MaxBits), + !IsSigned); + RHS = APSInt(IsSigned ? RHS.sextOrSelf(MaxBits) : RHS.zextOrSelf(MaxBits), + !IsSigned); + Result = APSInt(MaxBits, !IsSigned); +} + +// Find largest int. +switch (BuiltinOp) { +default: + llvm_unreachable("Invalid value for BuiltinOp"); +case Builtin::BI__builtin_add_overflow: +case Builtin::BI__builtin_sadd_overflow: +case Builtin::BI__builtin_saddl_overflow: +case Builtin::BI__builtin_saddll_overflow: +case Builtin::BI__builtin_uadd_overflow: +case Builtin::BI__builtin_uaddl_overflow: +case Builtin::BI__builtin_uaddll_overflow: + Result = LHS.isSigned() ? LHS.sadd_ov(RHS, DidOverflow) + : LHS.uadd_ov(RHS, DidOverflow); + break; +case Builtin::BI__builtin_sub_overflow: +case Builtin::BI__builtin_ssub_overflow: +case Builtin::BI__builtin_ssubl_overflow: +case Builtin::BI__builtin_ssubll_overflow: +case Builtin::BI__builtin_usub_overflow: +case Builtin::BI__builtin_usubl_overflow: +case Builtin::BI__builtin_usubll_overflow: + Result = LHS.isSigned() ? LHS.ssub_ov(RHS, DidOverflow) + : LHS.usub_ov(RHS, DidOverflow); + break; +case Builtin::BI__builtin_mul_overflow: +case Builtin::BI__builtin_smul_overflow: +case Builtin::BI__builtin_smull_overflow: +case Builtin::BI__builtin_smulll_overflow: +
[PATCH] D48106: implemented proto to llvm
emmettneyman updated this revision to Diff 151240. emmettneyman added a comment. - removed typo in emitted llvm insn Repository: rC Clang https://reviews.llvm.org/D48106 Files: tools/clang-fuzzer/CMakeLists.txt tools/clang-fuzzer/cxx_loop_proto.proto tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp Index: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp === --- tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp +++ tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp @@ -1,32 +1,31 @@ -//==-- loop_proto_to_cxx_main.cpp - Driver for protobuf-C++ conversion -==// +//==-- loop_proto_to_llvm_main.cpp - Driver for protobuf-LLVM conversion==// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===--===// // -// Implements a simple driver to print a C++ program from a protobuf with loops. +// Implements a simple driver to print a LLVM program from a protobuf with loops // //===--===// -// This is a copy and will be updated later to introduce changes #include #include #include #include -#include "proto_to_cxx.h" +#include "loop_proto_to_llvm.h" int main(int argc, char **argv) { for (int i = 1; i < argc; i++) { std::fstream in(argv[i]); std::string str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); -std::cout << "// " << argv[i] << std::endl; -std::cout << clang_fuzzer::LoopProtoToCxx( +std::cout << ";; " << argv[i] << std::endl; +std::cout << clang_fuzzer::LoopProtoToLLVM( reinterpret_cast(str.data()), str.size()); } } Index: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h === --- /dev/null +++ tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h @@ -0,0 +1,23 @@ +//==-- loop_proto_to_llvm.h - Protobuf-C++ conversion ==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// +// +// Defines functions for converting between protobufs and LLVM IR. +// +//===--===// + +#include +#include +#include + +namespace clang_fuzzer { +class LoopFunction; + +std::string LoopFunctionToLLVMString(const LoopFunction ); +std::string LoopProtoToLLVM(const uint8_t *data, size_t size); +} Index: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp === --- /dev/null +++ tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp @@ -0,0 +1,179 @@ +//==-- loop_proto_to_llvm.cpp - Protobuf-C++ conversion +//-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// +// +// Implements functions for converting between protobufs and LLVM IR. +// +// +//===--===// + +#include "loop_proto_to_llvm.h" +#include "cxx_loop_proto.pb.h" + +// The following is needed to convert protos in human-readable form +#include + +#include +#include + +namespace clang_fuzzer { + +// Forward decls +std::pair BinopToString(const BinaryOp ); +std::pair StateSeqToString(const StatementSeq ); + +// Counter variable to generate new LLVM IR variable names and wrapper function +int ctr = 0; +std::string get_var() { + ctr++; + return "%var" + std::to_string(ctr); +} + +// Proto to LLVM. + +std::pair ConstToString(const Const ) { + std::string alloca_var = get_var(); + std::string load_var = get_var(); + std::string val = std::to_string(x.val()); + std::string insns = alloca_var + " = alloca i32\n" + + "store i32 " + val + ", i32* " + alloca_var + "\n" + + load_var + " = load i32, i32* " + alloca_var + "\n"; + return std::make_pair(insns, load_var); +} +std::pair VarRefToString(const VarRef ) { + std::string arr; + switch(x.arr()) { + case VarRef::ARR_A: +arr = "%a"; +break; + case VarRef::ARR_B: +arr =
[PATCH] D48134: [CodeGen] make nan builtins pure rather than const (PR37778)
rsmith added a comment. Can we mark these as `argmemonly`? Repository: rL LLVM https://reviews.llvm.org/D48134 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48106: implemented proto to llvm
emmettneyman added a comment. In https://reviews.llvm.org/D48106#1130581, @morehouse wrote: > Where is the fuzz target? I wanted to implement the proto_to_llvm converter before the fuzz target. Repository: rC Clang https://reviews.llvm.org/D48106 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48106: implemented proto to llvm
emmettneyman updated this revision to Diff 151239. emmettneyman added a comment. - refactored loop_proto_to_llvm.cpp Repository: rC Clang https://reviews.llvm.org/D48106 Files: tools/clang-fuzzer/CMakeLists.txt tools/clang-fuzzer/cxx_loop_proto.proto tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp Index: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp === --- tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp +++ tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp @@ -1,32 +1,31 @@ -//==-- loop_proto_to_cxx_main.cpp - Driver for protobuf-C++ conversion -==// +//==-- loop_proto_to_llvm_main.cpp - Driver for protobuf-LLVM conversion==// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===--===// // -// Implements a simple driver to print a C++ program from a protobuf with loops. +// Implements a simple driver to print a LLVM program from a protobuf with loops // //===--===// -// This is a copy and will be updated later to introduce changes #include #include #include #include -#include "proto_to_cxx.h" +#include "loop_proto_to_llvm.h" int main(int argc, char **argv) { for (int i = 1; i < argc; i++) { std::fstream in(argv[i]); std::string str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); -std::cout << "// " << argv[i] << std::endl; -std::cout << clang_fuzzer::LoopProtoToCxx( +std::cout << ";; " << argv[i] << std::endl; +std::cout << clang_fuzzer::LoopProtoToLLVM( reinterpret_cast(str.data()), str.size()); } } Index: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h === --- /dev/null +++ tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h @@ -0,0 +1,23 @@ +//==-- loop_proto_to_llvm.h - Protobuf-C++ conversion ==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// +// +// Defines functions for converting between protobufs and LLVM IR. +// +//===--===// + +#include +#include +#include + +namespace clang_fuzzer { +class LoopFunction; + +std::string LoopFunctionToLLVMString(const LoopFunction ); +std::string LoopProtoToLLVM(const uint8_t *data, size_t size); +} Index: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp === --- /dev/null +++ tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp @@ -0,0 +1,179 @@ +//==-- loop_proto_to_llvm.cpp - Protobuf-C++ conversion +//-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// +// +// Implements functions for converting between protobufs and LLVM IR. +// +// +//===--===// + +#include "loop_proto_to_llvm.h" +#include "cxx_loop_proto.pb.h" + +// The following is needed to convert protos in human-readable form +#include + +#include +#include + +namespace clang_fuzzer { + +// Forward decls +std::pair BinopToString(const BinaryOp ); +std::pair StateSeqToString(const StatementSeq ); + +// Counter variable to generate new LLVM IR variable names and wrapper function +int ctr = 0; +std::string get_var() { + ctr++; + return "%var" + std::to_string(ctr); +} + +// Proto to LLVM. + +std::pair ConstToString(const Const ) { + std::string alloca_var = get_var(); + std::string load_var = get_var(); + std::string val = std::to_string(x.val()); + std::string insns = alloca_var + " = alloca i32\n" + + "store i32 " + val + ", i32* " + alloca_var + "\n" + + load_var + " = load i32, i32* " + alloca_var + "\n"; + return std::make_pair(insns, load_var); +} +std::pair VarRefToString(const VarRef ) { + std::string arr; + switch(x.arr()) { + case VarRef::ARR_A: +arr = "%a"; +break; + case VarRef::ARR_B: +arr =
[PATCH] D48040: Implement constexpr __builtin_*_overflow
efriedma added a comment. Oh, sorry, I mixed up the two values. I meant that you should add a couple testcases to ensure the stored value is correct on overflow. https://reviews.llvm.org/D48040 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48132: [COFF] Add ARM64 intrinsics: __yield, __wfe, __wfi, __sev, __sevl
This revision was automatically updated to reflect the committed changes. Closed by commit rL334639: [COFF] Add ARM64 intrinsics: __yield, __wfe, __wfi, __sev, __sevl (authored by mgrang, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D48132?vs=151186=151218#toc Repository: rL LLVM https://reviews.llvm.org/D48132 Files: cfe/trunk/include/clang/Basic/BuiltinsAArch64.def cfe/trunk/lib/CodeGen/CGBuiltin.cpp cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c Index: cfe/trunk/include/clang/Basic/BuiltinsAArch64.def === --- cfe/trunk/include/clang/Basic/BuiltinsAArch64.def +++ cfe/trunk/include/clang/Basic/BuiltinsAArch64.def @@ -65,9 +65,15 @@ BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") +// MSVC LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES) // MSVC intrinsics for volatile but non-acquire/release loads and stores LANGBUILTIN(__iso_volatile_load8, "ccCD*", "n", ALL_MS_LANGUAGES) Index: cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c === --- cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c +++ cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c @@ -24,3 +24,38 @@ // CHECK-MSVC: @llvm.aarch64.isb(i32 0) // CHECK-LINUX: error: implicit declaration of function '__isb' + +void check__yield(void) { + __yield(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 1) +// CHECK-LINUX: error: implicit declaration of function '__yield' + +void check__wfe(void) { + __wfe(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 2) +// CHECK-LINUX: error: implicit declaration of function '__wfe' + +void check__wfi(void) { + __wfi(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 3) +// CHECK-LINUX: error: implicit declaration of function '__wfi' + +void check__sev(void) { + __sev(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 4) +// CHECK-LINUX: error: implicit declaration of function '__sev' + +void check__sevl(void) { + __sevl(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 5) +// CHECK-LINUX: error: implicit declaration of function '__sevl' Index: cfe/trunk/lib/CodeGen/CGBuiltin.cpp === --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp @@ -6362,18 +6362,23 @@ HintID = 0; break; case AArch64::BI__builtin_arm_yield: + case AArch64::BI__yield: HintID = 1; break; case AArch64::BI__builtin_arm_wfe: + case AArch64::BI__wfe: HintID = 2; break; case AArch64::BI__builtin_arm_wfi: + case AArch64::BI__wfi: HintID = 3; break; case AArch64::BI__builtin_arm_sev: + case AArch64::BI__sev: HintID = 4; break; case AArch64::BI__builtin_arm_sevl: + case AArch64::BI__sevl: HintID = 5; break; } Index: cfe/trunk/include/clang/Basic/BuiltinsAArch64.def === --- cfe/trunk/include/clang/Basic/BuiltinsAArch64.def +++ cfe/trunk/include/clang/Basic/BuiltinsAArch64.def @@ -65,9 +65,15 @@ BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") +// MSVC LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES) // MSVC intrinsics for volatile but non-acquire/release loads and stores LANGBUILTIN(__iso_volatile_load8, "ccCD*", "n", ALL_MS_LANGUAGES) Index: cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c === --- cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c +++ cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c @@ -24,3 +24,38 @@ // CHECK-MSVC: @llvm.aarch64.isb(i32 0) // CHECK-LINUX: error: implicit declaration of function '__isb' + +void check__yield(void) { + __yield(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 1) +// CHECK-LINUX: error: implicit declaration of function '__yield' + +void check__wfe(void) { + __wfe(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 2) +// CHECK-LINUX: error: implicit declaration of function '__wfe' + +void check__wfi(void) { + __wfi(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 3) +// CHECK-LINUX: error:
r334639 - [COFF] Add ARM64 intrinsics: __yield, __wfe, __wfi, __sev, __sevl
Author: mgrang Date: Wed Jun 13 11:49:35 2018 New Revision: 334639 URL: http://llvm.org/viewvc/llvm-project?rev=334639=rev Log: [COFF] Add ARM64 intrinsics: __yield, __wfe, __wfi, __sev, __sevl Summary: These intrinsics result in hint instructions. They are provided here for MSVC ARM64 compatibility. Reviewers: mstorsjo, compnerd, javed.absar Reviewed By: mstorsjo Subscribers: kristof.beyls, chrib, cfe-commits Differential Revision: https://reviews.llvm.org/D48132 Modified: cfe/trunk/include/clang/Basic/BuiltinsAArch64.def cfe/trunk/lib/CodeGen/CGBuiltin.cpp cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c Modified: cfe/trunk/include/clang/Basic/BuiltinsAArch64.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/BuiltinsAArch64.def?rev=334639=334638=334639=diff == --- cfe/trunk/include/clang/Basic/BuiltinsAArch64.def (original) +++ cfe/trunk/include/clang/Basic/BuiltinsAArch64.def Wed Jun 13 11:49:35 2018 @@ -65,9 +65,15 @@ BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") +// MSVC LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES) // MSVC intrinsics for volatile but non-acquire/release loads and stores LANGBUILTIN(__iso_volatile_load8, "ccCD*", "n", ALL_MS_LANGUAGES) Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=334639=334638=334639=diff == --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Wed Jun 13 11:49:35 2018 @@ -6362,18 +6362,23 @@ Value *CodeGenFunction::EmitAArch64Built HintID = 0; break; case AArch64::BI__builtin_arm_yield: + case AArch64::BI__yield: HintID = 1; break; case AArch64::BI__builtin_arm_wfe: + case AArch64::BI__wfe: HintID = 2; break; case AArch64::BI__builtin_arm_wfi: + case AArch64::BI__wfi: HintID = 3; break; case AArch64::BI__builtin_arm_sev: + case AArch64::BI__sev: HintID = 4; break; case AArch64::BI__builtin_arm_sevl: + case AArch64::BI__sevl: HintID = 5; break; } Modified: cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c?rev=334639=334638=334639=diff == --- cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c (original) +++ cfe/trunk/test/CodeGen/arm64-microsoft-intrinsics.c Wed Jun 13 11:49:35 2018 @@ -24,3 +24,38 @@ void check__isb(void) { // CHECK-MSVC: @llvm.aarch64.isb(i32 0) // CHECK-LINUX: error: implicit declaration of function '__isb' + +void check__yield(void) { + __yield(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 1) +// CHECK-LINUX: error: implicit declaration of function '__yield' + +void check__wfe(void) { + __wfe(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 2) +// CHECK-LINUX: error: implicit declaration of function '__wfe' + +void check__wfi(void) { + __wfi(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 3) +// CHECK-LINUX: error: implicit declaration of function '__wfi' + +void check__sev(void) { + __sev(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 4) +// CHECK-LINUX: error: implicit declaration of function '__sev' + +void check__sevl(void) { + __sevl(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 5) +// CHECK-LINUX: error: implicit declaration of function '__sevl' ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48132: [COFF] Add ARM64 intrinsics: __yield, __wfe, __wfi, __sev, __sevl
mstorsjo accepted this revision. mstorsjo added a comment. This revision is now accepted and ready to land. LGTM Repository: rC Clang https://reviews.llvm.org/D48132 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48040: Implement constexpr __builtin_*_overflow
erichkeane added a comment. I believe my tests DO validate the return value correctly, don't they? It uses a sentinel, but the ternary should check that return value, right? Or is there an obvious thing I'm missing? https://reviews.llvm.org/D48040 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48040: Implement constexpr __builtin_*_overflow
efriedma accepted this revision. efriedma added a comment. This revision is now accepted and ready to land. I'd like to see a couple of testcases ensuring the return value is correct on overflow (we had a problem with that for __builtin_mul_overflow in the past). Otherwise LGTM. https://reviews.llvm.org/D48040 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r334636 - [analyzer] Fix offset overflow check in MemRegion
Author: george.karpenkov Date: Wed Jun 13 11:32:19 2018 New Revision: 334636 URL: http://llvm.org/viewvc/llvm-project?rev=334636=rev Log: [analyzer] Fix offset overflow check in MemRegion rdar://39593879 https://bugs.llvm.org/show_bug.cgi?id=37142 Differential Revision: https://reviews.llvm.org/D48139 Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp cfe/trunk/test/Analysis/region_store_overflow.c Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=334636=334635=334636=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Wed Jun 13 11:32:19 2018 @@ -41,6 +41,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/CheckedArithmetic.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -1181,38 +1182,8 @@ const SymbolicRegion *MemRegion::getSymb return nullptr; } -/// Perform a given operation on two integers, return whether it overflows. -/// Optionally write the resulting output into \p Res. -static bool checkedOp( -int64_t LHS, -int64_t RHS, -std::function Op, -int64_t *Res = nullptr) { - llvm::APInt ALHS(/*BitSize=*/64, LHS, /*Signed=*/true); - llvm::APInt ARHS(/*BitSize=*/64, RHS, /*Signed=*/true); - bool Overflow; - llvm::APInt Out = Op(, ARHS, Overflow); - if (!Overflow && Res) -*Res = Out.getSExtValue(); - return Overflow; -} - -static bool checkedAdd( -int64_t LHS, -int64_t RHS, -int64_t *Res=nullptr) { - return checkedOp(LHS, RHS, ::APInt::sadd_ov, Res); -} - -static bool checkedMul( -int64_t LHS, -int64_t RHS, -int64_t *Res=nullptr) { - return checkedOp(LHS, RHS, ::APInt::smul_ov, Res); -} - RegionRawOffset ElementRegion::getAsArrayOffset() const { - CharUnits offset = CharUnits::Zero(); + int64_t offset = 0; const ElementRegion *ER = this; const MemRegion *superR = nullptr; ASTContext = getContext(); @@ -1224,7 +1195,7 @@ RegionRawOffset ElementRegion::getAsArra // FIXME: generalize to symbolic offsets. SVal index = ER->getIndex(); -if (Optional CI = index.getAs()) { +if (auto CI = index.getAs()) { // Update the offset. int64_t i = CI->getValue().getSExtValue(); @@ -1237,20 +1208,15 @@ RegionRawOffset ElementRegion::getAsArra break; } -CharUnits size = C.getTypeSizeInChars(elemType); - -int64_t Mult; -bool Overflow = checkedAdd(i, size.getQuantity(), ); -if (!Overflow) - Overflow = checkedMul(Mult, offset.getQuantity()); -if (Overflow) { +int64_t size = C.getTypeSizeInChars(elemType).getQuantity(); +if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) { + offset = *NewOffset; +} else { LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: " << "offset overflowing, returning unknown\n"); return nullptr; } - -offset += (i * size); } // Go to the next ElementRegion (if any). @@ -1262,7 +1228,7 @@ RegionRawOffset ElementRegion::getAsArra } assert(superR && "super region cannot be NULL"); - return RegionRawOffset(superR, offset); + return RegionRawOffset(superR, CharUnits::fromQuantity(offset)); } /// Returns true if \p Base is an immediate base class of \p Child Modified: cfe/trunk/test/Analysis/region_store_overflow.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/region_store_overflow.c?rev=334636=334635=334636=diff == --- cfe/trunk/test/Analysis/region_store_overflow.c (original) +++ cfe/trunk/test/Analysis/region_store_overflow.c Wed Jun 13 11:32:19 2018 @@ -1,6 +1,5 @@ // RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -verify %s -// expected-no-diagnostics int **h; int overflow_in_memregion(long j) { for (int l = 0;; ++l) { @@ -9,3 +8,9 @@ int overflow_in_memregion(long j) { } return 0; } + +void rdar39593879(long long *d) { + long e, f; + e = f = d[1]; // no-crash + for (; d[e];) f-- > 0; // expected-warning{{relational comparison result unused}}; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48100: Append new attributes to the end of an AttributeList.
Meinersbur updated this revision to Diff 151209. Meinersbur added a comment. - Remove obsolete comment - Refactor getOrderedEnableIfAttrs Repository: rC Clang https://reviews.llvm.org/D48100 Files: include/clang/Sema/AttributeList.h lib/AST/ItaniumMangle.cpp lib/Parse/ParseDecl.cpp lib/Sema/SemaOverload.cpp test/Index/annotate-comments-availability-attrs.cpp test/Index/complete-with-annotations.cpp test/Misc/ast-print-pragmas.cpp test/PCH/pragma-loop.cpp test/Parser/pragma-loop-safety.cpp test/Parser/pragma-loop.cpp test/Parser/pragma-unroll.cpp test/Sema/attr-availability-tvos.c test/Sema/attr-availability.c test/Sema/attr-coldhot.c test/Sema/attr-disable-tail-calls.c test/Sema/attr-long-call.c test/Sema/attr-micromips.c test/Sema/attr-notail.c test/Sema/attr-ownership.c test/Sema/attr-ownership.cpp test/Sema/attr-print.c test/Sema/attr-swiftcall.c test/Sema/attr-target-mv.c test/Sema/attr-visibility.c test/Sema/internal_linkage.c test/Sema/mips-interrupt-attr.c test/Sema/ms_abi-sysv_abi.c test/Sema/nullability.c test/Sema/stdcall-fastcall.c test/SemaCXX/attr-print.cpp test/SemaCXX/attr-swiftcall.cpp test/SemaCXX/decl-microsoft-call-conv.cpp test/SemaCXX/ms-uuid.cpp test/SemaOpenCL/address-spaces.cl test/SemaTemplate/attributes.cpp Index: test/SemaTemplate/attributes.cpp === --- test/SemaTemplate/attributes.cpp +++ test/SemaTemplate/attributes.cpp @@ -55,11 +55,11 @@ } // CHECK: FunctionTemplateDecl {{.*}} HasAnnotations -// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" // CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO" +// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" // CHECK: FunctionDecl {{.*}} HasAnnotations // CHECK: TemplateArgument type 'int' -// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" // CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO" +// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" template [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations(); void UseAnnotations() { HasAnnotations(); } Index: test/SemaOpenCL/address-spaces.cl === --- test/SemaOpenCL/address-spaces.cl +++ test/SemaOpenCL/address-spaces.cl @@ -58,8 +58,8 @@ void func_multiple_addr(void) { typedef __private int private_int_t; - __local __private int var1; // expected-error {{multiple address spaces specified for type}} - __local __private int *var2; // expected-error {{multiple address spaces specified for type}} + __private __local int var1; // expected-error {{multiple address spaces specified for type}} + __private __local int *var2; // expected-error {{multiple address spaces specified for type}} __local private_int_t var3; // expected-error {{multiple address spaces specified for type}} __local private_int_t *var4; // expected-error {{multiple address spaces specified for type}} } Index: test/SemaCXX/ms-uuid.cpp === --- test/SemaCXX/ms-uuid.cpp +++ test/SemaCXX/ms-uuid.cpp @@ -62,14 +62,14 @@ [uuid("22A0---C000-0049")] class C4 {}; // Both cl and clang-cl error out on this: -// expected-note@+1 {{previous uuid specified here}} -class __declspec(uuid("00A0---C000-0049")) // expected-error@+1 {{uuid does not match previous declaration}} +class __declspec(uuid("00A0---C000-0049")) +// expected-note@+1 {{previous uuid specified here}} __declspec(uuid("11A0---C000-0049")) C5; -// expected-note@+1 {{previous uuid specified here}} -[uuid("00A0---C000-0049"), // expected-error@+1 {{uuid does not match previous declaration}} +[uuid("00A0---C000-0049"), +// expected-note@+1 {{previous uuid specified here}} uuid("11A0---C000-0049")] class C6; // cl doesn't diagnose having one uuid each as []-style attributes and as Index: test/SemaCXX/decl-microsoft-call-conv.cpp === --- test/SemaCXX/decl-microsoft-call-conv.cpp +++ test/SemaCXX/decl-microsoft-call-conv.cpp @@ -161,7 +161,7 @@ // expected-error@+3 {{vectorcall and cdecl attributes are not compatible}} // expected-error@+2 {{stdcall and cdecl attributes are not compatible}} // expected-error@+1 {{fastcall and cdecl attributes are not compatible}} -void __cdecl __cdecl __stdcall __cdecl __fastcall __vectorcall multi_cc(int x); +void __vectorcall __fastcall __cdecl __stdcall __cdecl __cdecl multi_cc(int x); template void __stdcall StdcallTemplate(T) {} template <> void StdcallTemplate(int) {} Index: test/SemaCXX/attr-swiftcall.cpp === --- test/SemaCXX/attr-swiftcall.cpp +++ test/SemaCXX/attr-swiftcall.cpp @@ -7,7 +7,7 @@ int notAFunction SWIFTCALL; //
[PATCH] D47044: [analyzer] Ensure that we only visit a destructor for a reference if type information is available.
ormris added a comment. Thanks @george.karpenkov . I was wondering why it didn't close automatically. Repository: rC Clang https://reviews.llvm.org/D47044 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45616: [X86] Lower _mm[256|512]_cmp[.]_mask intrinsics to native llvm IR
spatel added inline comments. Comment at: lib/CodeGen/CGBuiltin.cpp:10107-10112 +case 0x0b: // FALSE_OQ +case 0x1b: // FALSE_OS + return llvm::Constant::getNullValue(ConvertType(E->getType())); +case 0x0f: // TRUE_UQ +case 0x1f: // TRUE_US + return llvm::Constant::getAllOnesValue(ConvertType(E->getType())); On 2nd thought, why are we optimizing when we have matching IR predicates for these? Just translate to FCMP_TRUE / FCMP_FALSE instead of special-casing these values. InstSimplify can handle the constant folding if optimization is on. https://reviews.llvm.org/D45616 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47044: [analyzer] Ensure that we only visit a destructor for a reference if type information is available.
george.karpenkov added a comment. > This change has been committed, so I'm closing this review. @ormris The process which should be followed here is to add a line (exactly) "Differential Revision: https://reviews.llvm.org/D47044; to the bottom of your commit message, so that the phabricator can cross-reference the review and the commit. Alternatively, you could use the "arc" tool which would do that for you. Repository: rC Clang https://reviews.llvm.org/D47044 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45616: [X86] Lower _mm[256|512]_cmp[.]_mask intrinsics to native llvm IR
GBuella updated this revision to Diff 151203. GBuella edited the summary of this revision. GBuella added a comment. Ignoring signaling behviour - and rounding mode with it. Also lowering `__builtin_ia32_cmpsd` and `__builtin_ia32_cmpss`. https://reviews.llvm.org/D45616 Files: lib/CodeGen/CGBuiltin.cpp test/CodeGen/avx-builtins.c test/CodeGen/avx-cmp-builtins.c test/CodeGen/avx2-builtins.c test/CodeGen/avx512f-builtins.c test/CodeGen/avx512vl-builtins.c Index: test/CodeGen/avx512vl-builtins.c === --- test/CodeGen/avx512vl-builtins.c +++ test/CodeGen/avx512vl-builtins.c @@ -1073,53 +1073,168 @@ __mmask8 test_mm256_cmp_ps_mask(__m256 __A, __m256 __B) { // CHECK-LABEL: @test_mm256_cmp_ps_mask - // CHECK: call <8 x i1> @llvm.x86.avx512.mask.cmp.ps.256 + // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}} return (__mmask8)_mm256_cmp_ps_mask(__A, __B, 0); } +__mmask8 test_mm256_cmp_ps_mask_true_uq(__m256 __A, __m256 __B) { + // CHECK-LABEL: @test_mm256_cmp_ps_mask_true_uq + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_TRUE_UQ); +} + +__mmask8 test_mm256_cmp_ps_mask_true_us(__m256 __A, __m256 __B) { + // CHECK-LABEL: @test_mm256_cmp_ps_mask_true_us + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_TRUE_US); +} + +__mmask8 test_mm256_cmp_ps_mask_false_oq(__m256 __A, __m256 __B) { + // CHECK-LABEL: @test_mm256_cmp_ps_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_FALSE_OQ); +} + +__mmask8 test_mm256_cmp_ps_mask_false_os(__m256 __A, __m256 __B) { + // CHECK-LABEL: @test_mm256_cmp_ps_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_FALSE_OS); +} + __mmask8 test_mm256_mask_cmp_ps_mask(__mmask8 m, __m256 __A, __m256 __B) { // CHECK-LABEL: @test_mm256_mask_cmp_ps_mask - // CHECK: [[CMP:%.*]] = call <8 x i1> @llvm.x86.avx512.mask.cmp.ps.256 - // CHECK: and <8 x i1> [[CMP]], {{.*}} + // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> %{{.*}}, %{{.*}} return _mm256_mask_cmp_ps_mask(m, __A, __B, 0); } __mmask8 test_mm_cmp_ps_mask(__m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_cmp_ps_mask - // CHECK: call <4 x i1> @llvm.x86.avx512.mask.cmp.ps.128 + // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} return (__mmask8)_mm_cmp_ps_mask(__A, __B, 0); } +__mmask8 test_mm_cmp_ps_mask_true_uq(__m128 __A, __m128 __B) { + // CHECK-LABEL: @test_mm_cmp_ps_mask_true_uq + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_TRUE_UQ); +} + +__mmask8 test_mm_cmp_ps_mask_true_us(__m128 __A, __m128 __B) { + // CHECK-LABEL: @test_mm_cmp_ps_mask_true_us + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_TRUE_US); +} + +__mmask8 test_mm_cmp_ps_mask_false_oq(__m128 __A, __m128 __B) { + // CHECK-LABEL: @test_mm_cmp_ps_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_FALSE_OQ); +} + +__mmask8 test_mm_cmp_ps_mask_false_os(__m128 __A, __m128 __B) { + // CHECK-LABEL: @test_mm_cmp_ps_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_FALSE_OS); +} + __mmask8 test_mm_mask_cmp_ps_mask(__mmask8 m, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_mask_cmp_ps_mask - // CHECK: [[CMP:%.*]] = call <4 x i1> @llvm.x86.avx512.mask.cmp.ps.128 - // CHECK: and <4 x i1> [[CMP]], {{.*}} + // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} + // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> + // CHECK: and <4 x i1> %{{.*}}, %{{.*}} return _mm_mask_cmp_ps_mask(m, __A, __B, 0); } __mmask8 test_mm256_cmp_pd_mask(__m256d __A, __m256d __B) { // CHECK-LABEL: @test_mm256_cmp_pd_mask - // CHECK: call <4 x i1> @llvm.x86.avx512.mask.cmp.pd.256 + // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} return (__mmask8)_mm256_cmp_pd_mask(__A, __B, 0); } +__mmask8 test_mm256_cmp_pd_mask_true_uq(__m256d __A, __m256d __B) { + // CHECK-LABEL: @test_mm256_cmp_pd_mask_true_uq + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_TRUE_UQ); +} + +__mmask8 test_mm256_cmp_pd_mask_true_us(__m256d __A, __m256d __B) { + // CHECK-LABEL: @test_mm256_cmp_pd_mask_true_us + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_TRUE_US); +} + +__mmask8 test_mm256_cmp_pd_mask_false_oq(__m256d __A, __m256d __B) { + // CHECK-LABEL: @test_mm256_cmp_pd_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_FALSE_OQ); +} + +__mmask8 test_mm256_cmp_pd_mask_false_os(__m256d __A, __m256d __B) { + // CHECK-LABEL: @test_mm256_cmp_pd_mask_false_os + //
[PATCH] D48134: [CodeGen] make nan builtins pure rather than const (PR37778)
This revision was automatically updated to reflect the committed changes. Closed by commit rL334628: [CodeGen] make nan builtins pure rather than const (PR37778) (authored by spatel, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D48134?vs=151187=151202#toc Repository: rL LLVM https://reviews.llvm.org/D48134 Files: cfe/trunk/include/clang/Basic/Builtins.def cfe/trunk/test/CodeGen/math-builtins.c Index: cfe/trunk/include/clang/Basic/Builtins.def === --- cfe/trunk/include/clang/Basic/Builtins.def +++ cfe/trunk/include/clang/Basic/Builtins.def @@ -137,14 +137,14 @@ BUILTIN(__builtin_modf , "ddd*" , "Fn") BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") -BUILTIN(__builtin_nan, "dcC*" , "ncF") -BUILTIN(__builtin_nanf, "fcC*" , "ncF") -BUILTIN(__builtin_nanl, "LdcC*", "ncF") -BUILTIN(__builtin_nanf128, "LLdcC*", "ncF") -BUILTIN(__builtin_nans, "dcC*" , "ncF") -BUILTIN(__builtin_nansf, "fcC*" , "ncF") -BUILTIN(__builtin_nansl, "LdcC*", "ncF") -BUILTIN(__builtin_nansf128, "LLdcC*", "ncF") +BUILTIN(__builtin_nan, "dcC*" , "FnU") +BUILTIN(__builtin_nanf, "fcC*" , "FnU") +BUILTIN(__builtin_nanl, "LdcC*", "FnU") +BUILTIN(__builtin_nanf128, "LLdcC*", "FnU") +BUILTIN(__builtin_nans, "dcC*" , "FnU") +BUILTIN(__builtin_nansf, "fcC*" , "FnU") +BUILTIN(__builtin_nansl, "LdcC*", "FnU") +BUILTIN(__builtin_nansf128, "LLdcC*", "FnU") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") BUILTIN(__builtin_powil, "LdLdi", "Fnc") Index: cfe/trunk/test/CodeGen/math-builtins.c === --- cfe/trunk/test/CodeGen/math-builtins.c +++ cfe/trunk/test/CodeGen/math-builtins.c @@ -90,25 +90,25 @@ __builtin_nan(c);__builtin_nanf(c); __builtin_nanl(c); __builtin_nanf128(c); -// NO__ERRNO: declare double @nan(i8*) [[READNONE]] -// NO__ERRNO: declare float @nanf(i8*) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] -// NO__ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] -// HAS_ERRNO: declare double @nan(i8*) [[READNONE:#[0-9]+]] -// HAS_ERRNO: declare float @nanf(i8*) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] -// HAS_ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] +// NO__ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]] +// NO__ERRNO: declare float @nanf(i8*) [[PURE]] +// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]] +// NO__ERRNO: declare fp128 @nanf128(i8*) [[PURE]] +// HAS_ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]] +// HAS_ERRNO: declare float @nanf(i8*) [[PURE]] +// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]] +// HAS_ERRNO: declare fp128 @nanf128(i8*) [[PURE]] __builtin_nans(c);__builtin_nansf(c); __builtin_nansl(c); __builtin_nansf128(c); -// NO__ERRNO: declare double @nans(i8*) [[READNONE]] -// NO__ERRNO: declare float @nansf(i8*) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] -// NO__ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] -// HAS_ERRNO: declare double @nans(i8*) [[READNONE]] -// HAS_ERRNO: declare float @nansf(i8*) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] -// HAS_ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] +// NO__ERRNO: declare double @nans(i8*) [[PURE]] +// NO__ERRNO: declare float @nansf(i8*) [[PURE]] +// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]] +// NO__ERRNO: declare fp128 @nansf128(i8*) [[PURE]] +// HAS_ERRNO: declare double @nans(i8*) [[PURE]] +// HAS_ERRNO: declare float @nansf(i8*) [[PURE]] +// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]] +// HAS_ERRNO: declare fp128 @nansf128(i8*) [[PURE]] __builtin_pow(f,f);__builtin_powf(f,f); __builtin_powl(f,f); @@ -188,7 +188,7 @@ // NO__ERRNO: declare double @cbrt(double) [[READNONE]] // NO__ERRNO: declare float @cbrtf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @cbrt(double) [[READNONE]] +// HAS_ERRNO: declare double @cbrt(double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare float @cbrtf(float) [[READNONE]] // HAS_ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] @@ -581,9 +581,11 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } Index:
r334628 - [CodeGen] make nan builtins pure rather than const (PR37778)
Author: spatel Date: Wed Jun 13 10:54:52 2018 New Revision: 334628 URL: http://llvm.org/viewvc/llvm-project?rev=334628=rev Log: [CodeGen] make nan builtins pure rather than const (PR37778) https://bugs.llvm.org/show_bug.cgi?id=37778 ...shows a miscompile resulting from marking nan builtins as 'const'. The nan libcalls/builtins take a pointer argument: http://www.cplusplus.com/reference/cmath/nan-function/ ...and the chars dereferenced by that arg are used to fill in the NaN constant payload bits. "const" means that the pointer argument isn't dereferenced. That's translated to "readnone" in LLVM. "pure" means that the pointer argument may be dereferenced. That's translated to "readonly" in LLVM. This change prevents the IR optimizer from killing the lead-up to the nan call here: double a() { char buf[4]; buf[0] = buf[1] = buf[2] = '9'; buf[3] = '\0'; return __builtin_nan(buf); } ...the optimizer isn't currently able to simplify this to a constant as we might hope, but this patch should solve the miscompile. Differential Revision: https://reviews.llvm.org/D48134 Modified: cfe/trunk/include/clang/Basic/Builtins.def cfe/trunk/test/CodeGen/math-builtins.c Modified: cfe/trunk/include/clang/Basic/Builtins.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=334628=334627=334628=diff == --- cfe/trunk/include/clang/Basic/Builtins.def (original) +++ cfe/trunk/include/clang/Basic/Builtins.def Wed Jun 13 10:54:52 2018 @@ -137,14 +137,14 @@ BUILTIN(__builtin_ldexpl, "LdLdi", "Fne" BUILTIN(__builtin_modf , "ddd*" , "Fn") BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") -BUILTIN(__builtin_nan, "dcC*" , "ncF") -BUILTIN(__builtin_nanf, "fcC*" , "ncF") -BUILTIN(__builtin_nanl, "LdcC*", "ncF") -BUILTIN(__builtin_nanf128, "LLdcC*", "ncF") -BUILTIN(__builtin_nans, "dcC*" , "ncF") -BUILTIN(__builtin_nansf, "fcC*" , "ncF") -BUILTIN(__builtin_nansl, "LdcC*", "ncF") -BUILTIN(__builtin_nansf128, "LLdcC*", "ncF") +BUILTIN(__builtin_nan, "dcC*" , "FnU") +BUILTIN(__builtin_nanf, "fcC*" , "FnU") +BUILTIN(__builtin_nanl, "LdcC*", "FnU") +BUILTIN(__builtin_nanf128, "LLdcC*", "FnU") +BUILTIN(__builtin_nans, "dcC*" , "FnU") +BUILTIN(__builtin_nansf, "fcC*" , "FnU") +BUILTIN(__builtin_nansl, "LdcC*", "FnU") +BUILTIN(__builtin_nansf128, "LLdcC*", "FnU") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") BUILTIN(__builtin_powil, "LdLdi", "Fnc") Modified: cfe/trunk/test/CodeGen/math-builtins.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/math-builtins.c?rev=334628=334627=334628=diff == --- cfe/trunk/test/CodeGen/math-builtins.c (original) +++ cfe/trunk/test/CodeGen/math-builtins.c Wed Jun 13 10:54:52 2018 @@ -90,25 +90,25 @@ void foo(double *d, float f, float *fp, __builtin_nan(c);__builtin_nanf(c); __builtin_nanl(c); __builtin_nanf128(c); -// NO__ERRNO: declare double @nan(i8*) [[READNONE]] -// NO__ERRNO: declare float @nanf(i8*) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] -// NO__ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] -// HAS_ERRNO: declare double @nan(i8*) [[READNONE:#[0-9]+]] -// HAS_ERRNO: declare float @nanf(i8*) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] -// HAS_ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] +// NO__ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]] +// NO__ERRNO: declare float @nanf(i8*) [[PURE]] +// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]] +// NO__ERRNO: declare fp128 @nanf128(i8*) [[PURE]] +// HAS_ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]] +// HAS_ERRNO: declare float @nanf(i8*) [[PURE]] +// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]] +// HAS_ERRNO: declare fp128 @nanf128(i8*) [[PURE]] __builtin_nans(c);__builtin_nansf(c); __builtin_nansl(c); __builtin_nansf128(c); -// NO__ERRNO: declare double @nans(i8*) [[READNONE]] -// NO__ERRNO: declare float @nansf(i8*) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] -// NO__ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] -// HAS_ERRNO: declare double @nans(i8*) [[READNONE]] -// HAS_ERRNO: declare float @nansf(i8*) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] -// HAS_ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] +// NO__ERRNO: declare double @nans(i8*) [[PURE]] +// NO__ERRNO: declare float @nansf(i8*) [[PURE]] +// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]] +// NO__ERRNO: declare fp128 @nansf128(i8*) [[PURE]] +// HAS_ERRNO: declare double @nans(i8*) [[PURE]] +// HAS_ERRNO: declare float @nansf(i8*) [[PURE]] +// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]] +// HAS_ERRNO: declare fp128 @nansf128(i8*) [[PURE]] __builtin_pow(f,f);__builtin_powf(f,f); __builtin_powl(f,f);
[PATCH] D46915: [Fixed Point Arithmetic] Fixed Point Precision Bits and Fixed Point Literals
leonardchan added inline comments. Comment at: include/clang/Basic/TargetInfo.h:89 + // corresponding unsaturated types. + unsigned char ShortAccumFBits, ShortAccumIBits; + unsigned char AccumFBits, AccumIBits; ebevhan wrote: > leonardchan wrote: > > ebevhan wrote: > > > leonardchan wrote: > > > > ebevhan wrote: > > > > > I suspect it's still possible to calculate the ibits based on the > > > > > fbits, even for _Accum. > > > > > > > > > > Are the unsigned values needed? The fbits for unsigned _Fract are the > > > > > same as for signed _Fract if SameFBits is set, and +1 otherwise. The > > > > > same should go for unsigned _Accum, but I don't think it's entirely > > > > > clear how this affects the integral part. > > > > Similar to the previous comment, if we choose to make SameFBits > > > > dependent on/controlled by the target, then I think it would be better > > > > for the target to explicitly specify the integral bits since there > > > > could be some cases where there may be padding (such as for unsigned > > > > _Accum types if this flag is set), and in this case, I think it should > > > > be explicit that the `bit_width != IBits + FBits`. > > > > > > > > We also can't fill in that padding for the unsigned _Accum types as an > > > > extra integral bit since the standard says that `"each signed accum > > > > type has at least as many integral bits as its corresponding unsigned > > > > accum type".` > > > > > > > > For the unsigned _Fract values, I think we can get rid of them if we > > > > choose to keep the flag instead, but it would no longer apply to > > > > unsigned _Accum types since it would allow for extra padding in these > > > > types and would conflict with the logic of `bit_width == IBits + FBits` > > > > > > > > For now, I actually think the simplest option is to keep these target > > > > properties, but have the target override them individually, with checks > > > > to make sure the values adhere to the standard. > > > Is it not the case that `bitwidth != IBits + FBits` for signed types > > > only? Signed types require a sign bit (which is neither a fractional bit > > > nor an integral bit, according to spec) but unsigned types do not, and if > > > IBits and FBits for the signed and unsigned types are the same, the MSB > > > is simply a padding bit, at least for _Accum (for _Fract everything above > > > the fbits is padding). > > > > > > My reasoning for keeping the number of configurable values down was to > > > limit the number of twiddly knobs to make the implementation simpler. > > > Granting a lot of freedom is nice, but I suspect that it will be quite > > > hard to get the implementation working properly for every valid > > > configuration. I also don't really see much of a reason for `FBits != > > > UFBits` in general. I know the spec gives a recommendation to implement > > > it that way, but I think the benefit of normalizing the signed and > > > unsigned representations outweighs the lost bit in the unsigned type. > > > > > > It's hard to say what the differences are beyond that since I'm not sure > > > how you plan on treating padding bits. In our implementation, padding > > > bits (the MSB in all of the unsigned types for us) after any operation > > > are zeroed. > > I see. The implementation would be much simpler this way. The initial idea > > was to treat the padding bits as "don't care" bits where we would mask only > > the data bits when doing operations like comparisons that look at the whole > > integer. > That does work, but for binary operations it means you might need multiple > maskings per operation. If you mask after every operation instead, you only > need one. In our implementation, the only padding bit we have is the MSB in > the unsigned types. We simply insert a 'bit clear' after every operation that > produces an unsigned type (with some exceptions). > > The E-C spec says that padding bits are 'unspecified', but > implementation-wise, they have to be defined to something in order to operate > on them. So long as you ensure that it is never possible to observe anything > but zero in those bits from a program perspective, most operations just work. > Naturally, there are ways to subvert this design. If you have a `signed > _Fract *` and cast it to an `unsigned _Fract *` and the values happen to be > negative, the padding bit will be set and you'll get exciting behavior. > > Although... I just realized that the topmost half of the `_Fract`s in your > configuration is all padding. That might make things a bit more complicated > for things like signed types... Ideally the sign bit would be extended into > the padding for those. Yeah, I initially had 2 general purpose ideas for handling the padding: - Zero/sign extend them after all operations that modify the value (+, *, <<, casting to another type, ...). This way we know the sign part of a fixed point type,
[PATCH] D47672: [Headers] Add _Interlocked*_HLEAcquire/_HLERelease
craig.topper added a comment. FWIW, I found a cfe-dev thread about adding HLE support http://lists.llvm.org/pipermail/cfe-dev/2013-February/028031.html And a bunch of dead patches in phabricator https://reviews.llvm.org/people/revisions/110/ I also spoke to Andi Kleen here at Intel to make sure I got these inline assembly versions correct. And he's not sure CPython should be using these the way it is. It looks like they try to use the HLE versions anytime the memory order is acquire/release. But HLE isn't suitable for every acquire/release. https://reviews.llvm.org/D47672 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48134: [CodeGen] make nan builtins pure rather than const (PR37778)
lebedev.ri accepted this revision. lebedev.ri added a comment. This revision is now accepted and ready to land. Makes sense. https://reviews.llvm.org/D48134 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45616: [X86] Lower _mm[256|512]_cmp[.]_mask intrinsics to native llvm IR
GBuella added inline comments. Comment at: lib/CodeGen/CGBuiltin.cpp:10090-10100 +// _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector +// on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0... +if (CC == 0xf || CC == 0xb || CC == 0x1b || CC == 0x1f) { + llvm::Type *ResultType = ConvertType(E->getType()); + + Value *Constant = (CC == 0xf || CC == 0x1f) ? + llvm::Constant::getAllOnesValue(ResultType) : spatel wrote: > llvm::Type *ResultType = ConvertType(E->getType()); > if (CC == 0x0f || CC == 0x1f) > return llvm::Constant::getAllOnesValue(ResultType); > if (CC == 0x0b || CC == 0x1b) > return llvm::Constant::getNullValue(ResultType); > > ? > > Also, can we use the defined predicate names instead of hex values in this > code? Well, I believe we would need to predefine them first. I only found those in the client header `avxintrin.h`. https://reviews.llvm.org/D45616 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[libcxx] r334621 - Merging r323390:
Author: tstellar Date: Wed Jun 13 09:57:18 2018 New Revision: 334621 URL: http://llvm.org/viewvc/llvm-project?rev=334621=rev Log: Merging r323390: r323390 | ericwf | 2018-01-24 16:02:48 -0800 (Wed, 24 Jan 2018) | 9 lines Fix PR35564 - std::list splice/erase incorrectly throw in debug mode. There was a bug in the implementation of splice where the container sizes were updated before decrementing one of the iterators. Afterwards, the result of decrementing the iterator was flagged as UB by the debug implementation because the container was reported to be empty. This patch fixes that bug by delaying the updating of the container sizes until after the iterators have been correctly constructed. Modified: libcxx/branches/release_60/include/list libcxx/branches/release_60/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp Modified: libcxx/branches/release_60/include/list URL: http://llvm.org/viewvc/llvm-project/libcxx/branches/release_60/include/list?rev=334621=334620=334621=diff == --- libcxx/branches/release_60/include/list (original) +++ libcxx/branches/release_60/include/list Wed Jun 13 09:57:18 2018 @@ -2058,15 +2058,15 @@ list<_Tp, _Alloc>::splice(const_iterator #endif if (__f != __l) { +__link_pointer __first = __f.__ptr_; +--__l; +__link_pointer __last = __l.__ptr_; if (this != &__c) { -size_type __s = _VSTD::distance(__f, __l); +size_type __s = _VSTD::distance(__f, __l) + 1; __c.__sz() -= __s; base::__sz() += __s; } -__link_pointer __first = __f.__ptr_; ---__l; -__link_pointer __last = __l.__ptr_; base::__unlink_nodes(__first, __last); __link_nodes(__p.__ptr_, __first, __last); #if _LIBCPP_DEBUG_LEVEL >= 2 Modified: libcxx/branches/release_60/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/branches/release_60/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp?rev=334621=334620=334621=diff == --- libcxx/branches/release_60/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp (original) +++ libcxx/branches/release_60/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp Wed Jun 13 09:57:18 2018 @@ -42,6 +42,7 @@ public: Base::run(); try { FrontOnEmptyContainer(); + if constexpr (CT != CT_ForwardList) { AssignInvalidates(); BackOnEmptyContainer(); @@ -50,6 +51,8 @@ public: InsertIterIterIter(); EmplaceIterValue(); EraseIterIter(); + } else { +SpliceFirstElemAfter(); } if constexpr (CT == CT_Vector || CT == CT_Deque || CT == CT_List) { PopBack(); @@ -57,12 +60,66 @@ public: if constexpr (CT == CT_List || CT == CT_Deque) { PopFront(); // FIXME: Run with forward list as well } + if constexpr (CT == CT_List || CT == CT_ForwardList) { +RemoveFirstElem(); + } + if constexpr (CT == CT_List) { +SpliceFirstElem(); + } } catch (...) { assert(false && "uncaught debug exception"); } } private: + static void RemoveFirstElem() { +// See llvm.org/PR35564 +CHECKPOINT("remove()"); +{ + Container C = makeContainer(1); + auto FirstVal = *(C.begin()); + C.remove(FirstVal); + assert(C.empty()); +} +{ + Container C = {1, 1, 1, 1}; + auto FirstVal = *(C.begin()); + C.remove(FirstVal); + assert(C.empty()); +} + } + + static void SpliceFirstElem() { +// See llvm.org/PR35564 +CHECKPOINT("splice()"); +{ + Container C = makeContainer(1); + Container C2; + C2.splice(C2.end(), C, C.begin(), ++C.begin()); +} +{ + Container C = makeContainer(1); + Container C2; + C2.splice(C2.end(), C, C.begin()); +} + } + + + static void SpliceFirstElemAfter() { +// See llvm.org/PR35564 +CHECKPOINT("splice()"); +{ + Container C = makeContainer(1); + Container C2; + C2.splice_after(C2.begin(), C, C.begin(), ++C.begin()); +} +{ + Container C = makeContainer(1); + Container C2; + C2.splice_after(C2.begin(), C, C.begin()); +} + } + static void AssignInvalidates() { CHECKPOINT("assign(Size, Value)"); Container C(allocator_type{}); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47044: [analyzer] Ensure that we only visit a destructor for a reference if type information is available.
ormris closed this revision. ormris added a comment. This change has been committed, so I'm closing this review. https://reviews.llvm.org/rC334554 Repository: rC Clang https://reviews.llvm.org/D47044 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48036: [CUDA] Make min/max shims host+device.
tra added a comment. Ack. https://reviews.llvm.org/D48036 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48134: [CodeGen] make nan builtins pure rather than const (PR37778)
spatel created this revision. spatel added reviewers: gfalcon, lebedev.ri. Herald added a subscriber: mcrosier. https://bugs.llvm.org/show_bug.cgi?id=37778 ...shows a miscompile resulting from marking nan builtins as 'const'. The nan libcalls/builtins take a pointer argument: http://www.cplusplus.com/reference/cmath/nan-function/ ...and the chars dereferenced by that arg are used to fill in the NaN constant payload bits. "const" means that the pointer argument isn't dereferenced. That's translated to "readnone" in LLVM. "pure" means that the pointer argument may be dereferenced. That's translated to "readonly" in LLVM. This change prevents the IR optimizer from killing the lead-up to the nan call here: double a() { char buf[4]; buf[0] = buf[1] = buf[2] = '9'; buf[3] = '\0'; return __builtin_nan(buf); } ...the optimizer isn't currently able to simplify this to a constant as we might hope, but this patch should solve the miscompile. https://reviews.llvm.org/D48134 Files: include/clang/Basic/Builtins.def test/CodeGen/math-builtins.c Index: test/CodeGen/math-builtins.c === --- test/CodeGen/math-builtins.c +++ test/CodeGen/math-builtins.c @@ -90,25 +90,25 @@ __builtin_nan(c);__builtin_nanf(c); __builtin_nanl(c); __builtin_nanf128(c); -// NO__ERRNO: declare double @nan(i8*) [[READNONE]] -// NO__ERRNO: declare float @nanf(i8*) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] -// NO__ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] -// HAS_ERRNO: declare double @nan(i8*) [[READNONE:#[0-9]+]] -// HAS_ERRNO: declare float @nanf(i8*) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] -// HAS_ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] +// NO__ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]] +// NO__ERRNO: declare float @nanf(i8*) [[PURE]] +// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]] +// NO__ERRNO: declare fp128 @nanf128(i8*) [[PURE]] +// HAS_ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]] +// HAS_ERRNO: declare float @nanf(i8*) [[PURE]] +// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]] +// HAS_ERRNO: declare fp128 @nanf128(i8*) [[PURE]] __builtin_nans(c);__builtin_nansf(c); __builtin_nansl(c); __builtin_nansf128(c); -// NO__ERRNO: declare double @nans(i8*) [[READNONE]] -// NO__ERRNO: declare float @nansf(i8*) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] -// NO__ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] -// HAS_ERRNO: declare double @nans(i8*) [[READNONE]] -// HAS_ERRNO: declare float @nansf(i8*) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] -// HAS_ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] +// NO__ERRNO: declare double @nans(i8*) [[PURE]] +// NO__ERRNO: declare float @nansf(i8*) [[PURE]] +// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]] +// NO__ERRNO: declare fp128 @nansf128(i8*) [[PURE]] +// HAS_ERRNO: declare double @nans(i8*) [[PURE]] +// HAS_ERRNO: declare float @nansf(i8*) [[PURE]] +// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]] +// HAS_ERRNO: declare fp128 @nansf128(i8*) [[PURE]] __builtin_pow(f,f);__builtin_powf(f,f); __builtin_powl(f,f); @@ -188,7 +188,7 @@ // NO__ERRNO: declare double @cbrt(double) [[READNONE]] // NO__ERRNO: declare float @cbrtf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @cbrt(double) [[READNONE]] +// HAS_ERRNO: declare double @cbrt(double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare float @cbrtf(float) [[READNONE]] // HAS_ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] @@ -581,9 +581,11 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } Index: include/clang/Basic/Builtins.def === --- include/clang/Basic/Builtins.def +++ include/clang/Basic/Builtins.def @@ -137,14 +137,14 @@ BUILTIN(__builtin_modf , "ddd*" , "Fn") BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") -BUILTIN(__builtin_nan, "dcC*" , "ncF") -BUILTIN(__builtin_nanf, "fcC*" , "ncF") -BUILTIN(__builtin_nanl, "LdcC*", "ncF") -BUILTIN(__builtin_nanf128, "LLdcC*", "ncF") -BUILTIN(__builtin_nans, "dcC*" , "ncF") -BUILTIN(__builtin_nansf, "fcC*" , "ncF") -BUILTIN(__builtin_nansl, "LdcC*",
r334619 - [Basic] Fix -Wreorder warning
Author: d0k Date: Wed Jun 13 09:45:12 2018 New Revision: 334619 URL: http://llvm.org/viewvc/llvm-project?rev=334619=rev Log: [Basic] Fix -Wreorder warning Just use field initializers that don't suffer from this problem Modified: cfe/trunk/lib/Basic/Targets/PPC.h Modified: cfe/trunk/lib/Basic/Targets/PPC.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/PPC.h?rev=334619=334618=334619=diff == --- cfe/trunk/lib/Basic/Targets/PPC.h (original) +++ cfe/trunk/lib/Basic/Targets/PPC.h Wed Jun 13 09:45:12 2018 @@ -49,33 +49,30 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetI } ArchDefineTypes; - ArchDefineTypes ArchDefs; + ArchDefineTypes ArchDefs = ArchDefineNone; static const Builtin::Info BuiltinInfo[]; static const char *const GCCRegNames[]; static const TargetInfo::GCCRegAlias GCCRegAliases[]; std::string CPU; // Target cpu features. - bool HasAltivec; - bool HasVSX; - bool HasP8Vector; - bool HasP8Crypto; - bool HasDirectMove; - bool HasQPX; - bool HasHTM; - bool HasBPERMD; - bool HasExtDiv; - bool HasP9Vector; + bool HasAltivec = false; + bool HasVSX = false; + bool HasP8Vector = false; + bool HasP8Crypto = false; + bool HasDirectMove = false; + bool HasQPX = false; + bool HasHTM = false; + bool HasBPERMD = false; + bool HasExtDiv = false; + bool HasP9Vector = false; protected: std::string ABI; public: PPCTargetInfo(const llvm::Triple , const TargetOptions &) - : TargetInfo(Triple), HasAltivec(false), HasVSX(false), -HasP8Vector(false), HasP8Crypto(false), HasDirectMove(false), -HasQPX(false), HasHTM(false), HasBPERMD(false), HasExtDiv(false), -HasP9Vector(false), ArchDefs(ArchDefineNone) { + : TargetInfo(Triple) { SuitableAlign = 128; SimdDefaultAlign = 128; LongDoubleWidth = LongDoubleAlign = 128; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48036: [CUDA] Make min/max shims host+device.
jlebar added a comment. > Last comment in the bug pointed out that those overloads should be constexpr > in c++14. Maybe in a separate patch, though. Yeah, would prefer to do it in a separate patch. It's possible that having constexpr min/max in C++14 mode *without a C++14 standard library* will cause problems. (Don't mean to FUD it -- we should try. I just would like to be able to roll them back separately. :) https://reviews.llvm.org/D48036 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35110: [Analyzer] Constraint Manager Negates Difference
baloghadamsoftware added a comment. Herald added a subscriber: mikhail.ramalho. Any idea how to proceed? https://reviews.llvm.org/D35110 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46024: [clang-format] Add SpaceBeforeCpp11BracedList option.
rkirsling added a comment. I'll need someone to commit. Thanks! Repository: rC Clang https://reviews.llvm.org/D46024 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48027: [analyzer] Improve `CallDescription` to handle c++ method.
xazax.hun added inline comments. Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:32 check::PostCall> { - CallDescription CStrFn; + const llvm::SmallVector CStrFnFamily = { +{"std::basic_string::c_str"}, {"std::basic_string::c_str"}, I am not sure if this is the right solution in case of this check. We should track `c_str` calls regardless of what the template parameter is, so supporting any instantiation of `basic_string` is desired. This might not be the case, however, for other checks. If we think it is more likely we do not care about the template arguments, maybe a separate API could be used, where we pass the qualified name of the class separately without the template arguments. Alternatively, we could use matches name so the users could use regexps. At this point I also wonder what isCalled API gives us compared to matchers? Maybe it is more convenient to use than calling a `match`. Also, isCalled API has an IdentifierInfo cached which could be used for relatively efficient checks. @NoQ what do you think? Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:65 auto *TypeDecl = TypedR->getValueType()->getAsCXXRecordDecl(); if (TypeDecl->getName() != "basic_string") return; If we check for fully qualified names, this check might be redundant. Comment at: lib/StaticAnalyzer/Core/CallEvent.cpp:273 + auto Matches = + match(namedDecl(hasName(CD.FuncName)).bind("match_qualified_name"), *ND, +LCtx->getAnalysisDeclContext()->getASTContext()); Doesn't match also traverse the subtree of the AST? We only need to check if that particular node matches the qualified name. I wonder if we could, during the traversal, find another node that is a match unintentionally. Repository: rC Clang https://reviews.llvm.org/D48027 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48132: [COFF] Add ARM64 intrinsics: __yield, __wfe, __wfi, __sev, __sevl
mgrang created this revision. mgrang added reviewers: mstorsjo, compnerd. Herald added a reviewer: javed.absar. Herald added subscribers: chrib, kristof.beyls. These intrinsics result in hint instructions. They are provided here for MSVC ARM64 compatibility. Repository: rC Clang https://reviews.llvm.org/D48132 Files: include/clang/Basic/BuiltinsAArch64.def lib/CodeGen/CGBuiltin.cpp test/CodeGen/arm64-microsoft-intrinsics.c Index: test/CodeGen/arm64-microsoft-intrinsics.c === --- test/CodeGen/arm64-microsoft-intrinsics.c +++ test/CodeGen/arm64-microsoft-intrinsics.c @@ -24,3 +24,38 @@ // CHECK-MSVC: @llvm.aarch64.isb(i32 0) // CHECK-LINUX: error: implicit declaration of function '__isb' + +void check__yield(void) { + __yield(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 1) +// CHECK-LINUX: error: implicit declaration of function '__yield' + +void check__wfe(void) { + __wfe(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 2) +// CHECK-LINUX: error: implicit declaration of function '__wfe' + +void check__wfi(void) { + __wfi(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 3) +// CHECK-LINUX: error: implicit declaration of function '__wfi' + +void check__sev(void) { + __sev(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 4) +// CHECK-LINUX: error: implicit declaration of function '__sev' + +void check__sevl(void) { + __sevl(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 5) +// CHECK-LINUX: error: implicit declaration of function '__sevl' Index: lib/CodeGen/CGBuiltin.cpp === --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -6362,18 +6362,23 @@ HintID = 0; break; case AArch64::BI__builtin_arm_yield: + case AArch64::BI__yield: HintID = 1; break; case AArch64::BI__builtin_arm_wfe: + case AArch64::BI__wfe: HintID = 2; break; case AArch64::BI__builtin_arm_wfi: + case AArch64::BI__wfi: HintID = 3; break; case AArch64::BI__builtin_arm_sev: + case AArch64::BI__sev: HintID = 4; break; case AArch64::BI__builtin_arm_sevl: + case AArch64::BI__sevl: HintID = 5; break; } Index: include/clang/Basic/BuiltinsAArch64.def === --- include/clang/Basic/BuiltinsAArch64.def +++ include/clang/Basic/BuiltinsAArch64.def @@ -65,9 +65,15 @@ BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") +// MSVC LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES) // MSVC intrinsics for volatile but non-acquire/release loads and stores LANGBUILTIN(__iso_volatile_load8, "ccCD*", "n", ALL_MS_LANGUAGES) Index: test/CodeGen/arm64-microsoft-intrinsics.c === --- test/CodeGen/arm64-microsoft-intrinsics.c +++ test/CodeGen/arm64-microsoft-intrinsics.c @@ -24,3 +24,38 @@ // CHECK-MSVC: @llvm.aarch64.isb(i32 0) // CHECK-LINUX: error: implicit declaration of function '__isb' + +void check__yield(void) { + __yield(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 1) +// CHECK-LINUX: error: implicit declaration of function '__yield' + +void check__wfe(void) { + __wfe(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 2) +// CHECK-LINUX: error: implicit declaration of function '__wfe' + +void check__wfi(void) { + __wfi(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 3) +// CHECK-LINUX: error: implicit declaration of function '__wfi' + +void check__sev(void) { + __sev(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 4) +// CHECK-LINUX: error: implicit declaration of function '__sev' + +void check__sevl(void) { + __sevl(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 5) +// CHECK-LINUX: error: implicit declaration of function '__sevl' Index: lib/CodeGen/CGBuiltin.cpp === --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -6362,18 +6362,23 @@ HintID = 0; break; case AArch64::BI__builtin_arm_yield: + case AArch64::BI__yield: HintID = 1; break; case AArch64::BI__builtin_arm_wfe: + case AArch64::BI__wfe: HintID = 2; break; case AArch64::BI__builtin_arm_wfi: + case AArch64::BI__wfi: HintID = 3; break; case AArch64::BI__builtin_arm_sev: + case AArch64::BI__sev: HintID = 4; break; case AArch64::BI__builtin_arm_sevl: + case AArch64::BI__sevl: HintID = 5; break; } Index: include/clang/Basic/BuiltinsAArch64.def
[PATCH] D46911: [Fixed Point Arithmetic] Addition of the remaining fixed point types and their saturated equivalents
leonardchan added inline comments. Comment at: test/Frontend/fixed_point_bit_widths.c:44 + +// CHECK-NEXT: @size_SsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SF = dso_local global i{{[0-9]+}} 4 ebevhan wrote: > Wait; should these dso_local be `{{.*}}`? They should, I forgot to get the latest diff which checks this since not all targets produce `dso_local`. Repository: rC Clang https://reviews.llvm.org/D46911 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46911: [Fixed Point Arithmetic] Addition of the remaining fixed point types and their saturated equivalents
leonardchan updated this revision to Diff 151184. leonardchan marked an inline comment as done. Repository: rC Clang https://reviews.llvm.org/D46911 Files: include/clang/AST/ASTContext.h include/clang/AST/BuiltinTypes.def include/clang/AST/Type.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/Specifiers.h include/clang/Basic/TargetInfo.h include/clang/Basic/TokenKinds.def include/clang/Sema/DeclSpec.h include/clang/Serialization/ASTBitCodes.h lib/AST/ASTContext.cpp lib/AST/ExprConstant.cpp lib/AST/ItaniumMangle.cpp lib/AST/MicrosoftMangle.cpp lib/AST/NSAPI.cpp lib/AST/Type.cpp lib/AST/TypeLoc.cpp lib/Analysis/PrintfFormatString.cpp lib/Basic/TargetInfo.cpp lib/CodeGen/CGDebugInfo.cpp lib/CodeGen/CodeGenTypes.cpp lib/CodeGen/ItaniumCXXABI.cpp lib/Index/USRGeneration.cpp lib/Parse/ParseDecl.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/SemaType.cpp lib/Serialization/ASTCommon.cpp lib/Serialization/ASTReader.cpp test/Frontend/fixed_point.c test/Frontend/fixed_point_bit_widths.c test/Frontend/fixed_point_errors.c test/Frontend/fixed_point_errors.cpp Index: test/Frontend/fixed_point_errors.cpp === --- test/Frontend/fixed_point_errors.cpp +++ test/Frontend/fixed_point_errors.cpp @@ -1,5 +1,9 @@ +// RUN: %clang_cc1 -x c++ %s -verify // RUN: %clang_cc1 -x c++ -ffixed-point %s -verify // Name namgling is not provided for fixed point types in c++ _Accum accum; // expected-error{{unknown type name '_Accum'}} +_Fract fract; // expected-error{{unknown type name '_Fract'}} +_Sat _Accum sat_accum; // expected-error{{unknown type name '_Sat'}} +// expected-error@-1{{expected ';' after top level declarator}} Index: test/Frontend/fixed_point_errors.c === --- test/Frontend/fixed_point_errors.c +++ test/Frontend/fixed_point_errors.c @@ -5,6 +5,14 @@ long long _Accum longlong_accum; // expected-error{{'long long _Accum' is invalid}} unsigned long long _Accum u_longlong_accum; // expected-error{{'long long _Accum' is invalid}} +long long _Fract longlong_fract; // expected-error{{'long long _Fract' is invalid}} +unsigned long long _Fract u_longlong_fract; // expected-error{{'long long _Fract' is invalid}} + +_Sat long long _Accum sat_longlong_accum; // expected-error{{'long long _Accum' is invalid}} +_Sat unsigned long long _Accum sat_u_longlong_accum; // expected-error{{'long long _Accum' is invalid}} +_Sat long long _Fract sat_longlong_fract; // expected-error{{'long long _Fract' is invalid}} +_Sat unsigned long long _Fract sat_u_longlong_fract; // expected-error{{'long long _Fract' is invalid}} + /* Although _Complex types work with floating point numbers, the extension * provides no info for complex fixed point types. */ @@ -19,9 +27,67 @@ _Complex _Accum cmplx_s_accum; // expected-error{{'_Complex _Accum' is invalid}} _Complex long _Accum cmplx_s_long_accum;// expected-error{{'_Complex _Accum' is invalid}} +_Complex signed short _Fract cmplx_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex signed _Fract cmplx_s_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex signed long _Fract cmplx_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex unsigned short _Fract cmplx_u_short_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex unsigned _Fract cmplx_u_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex unsigned long _Fract cmplx_u_long_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex short _Fract cmplx_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex _Fract cmplx_s_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex long _Fract cmplx_s_long_fract;// expected-error{{'_Complex _Fract' is invalid}} + +_Complex _Sat signed short _Accum cmplx_sat_s_short_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat signed _Accum cmplx_sat_s_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat signed long _Accum cmplx_sat_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat unsigned short _Accum cmplx_sat_u_short_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat unsigned _Accum cmplx_sat_u_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat unsigned long _Accum cmplx_sat_u_long_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat short _Accum cmplx_sat_s_short_accum; // expected-error{{'_Complex _Accum' is
[PATCH] D48088: [PowerPC] The __float128 type should only be available on Power9
This revision was automatically updated to reflect the committed changes. Closed by commit rC334613: [PowerPC] The __float128 type should only be available on Power9 (authored by stefanp, committed by ). Herald added a subscriber: cfe-commits. Repository: rC Clang https://reviews.llvm.org/D48088 Files: lib/Basic/Targets/PPC.cpp lib/Basic/Targets/PPC.h test/Driver/ppc-f128-support-check.c test/Preprocessor/init.c test/Sema/float128-ld-incompatibility.cpp Index: test/Driver/ppc-f128-support-check.c === --- test/Driver/ppc-f128-support-check.c +++ test/Driver/ppc-f128-support-check.c @@ -0,0 +1,20 @@ +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128 +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=power9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128 + +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr8 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128 +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr7 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128 +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128 + +#ifdef __FLOAT128__ +static_assert(false, "__float128 enabled"); +#endif + +// HASF128: __float128 enabled +// HASF128-NOT: option '-mfloat128' cannot be specified with +// NOF128: option '-mfloat128' cannot be specified with + Index: test/Preprocessor/init.c === --- test/Preprocessor/init.c +++ test/Preprocessor/init.c @@ -6370,7 +6370,7 @@ // PPCPOWER9:#define _ARCH_PWR7 1 // PPCPOWER9:#define _ARCH_PWR9 1 // -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power8 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power9 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s // PPC-FLOAT128:#define __FLOAT128__ 1 // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-LINUX %s Index: test/Sema/float128-ld-incompatibility.cpp === --- test/Sema/float128-ld-incompatibility.cpp +++ test/Sema/float128-ld-incompatibility.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 \ -// RUN: -triple powerpc64le-unknown-linux-gnu -target-cpu pwr8 \ +// RUN: -triple powerpc64le-unknown-linux-gnu -target-cpu pwr9 \ // RUN: -target-feature +float128 %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -Wno-parentheses %s Index: lib/Basic/Targets/PPC.h === --- lib/Basic/Targets/PPC.h +++ lib/Basic/Targets/PPC.h @@ -18,13 +18,38 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Compiler.h" namespace clang { namespace targets { // PPC abstract base class class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { + + /// Flags for architecture specific defines. + typedef enum { +ArchDefineNone = 0, +ArchDefineName = 1 << 0, // is substituted for arch name. +ArchDefinePpcgr = 1 << 1, +ArchDefinePpcsq = 1 << 2, +ArchDefine440 = 1 << 3, +ArchDefine603 = 1 << 4, +ArchDefine604 = 1 << 5, +ArchDefinePwr4 = 1 << 6, +ArchDefinePwr5 = 1 << 7, +ArchDefinePwr5x = 1 << 8, +ArchDefinePwr6 = 1 << 9, +ArchDefinePwr6x = 1 << 10, +ArchDefinePwr7 = 1 << 11, +ArchDefinePwr8 = 1 << 12, +ArchDefinePwr9 = 1 << 13, +ArchDefineA2 = 1 << 14, +ArchDefineA2q = 1 << 15 + } ArchDefineTypes; + + + ArchDefineTypes ArchDefs; static const Builtin::Info BuiltinInfo[]; static const char *const GCCRegNames[]; static const TargetInfo::GCCRegAlias GCCRegAliases[]; @@ -50,34 +75,13 @@ : TargetInfo(Triple), HasAltivec(false), HasVSX(false), HasP8Vector(false), HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false), HasBPERMD(false), HasExtDiv(false), -HasP9Vector(false) { +HasP9Vector(false), ArchDefs(ArchDefineNone) { SuitableAlign = 128; SimdDefaultAlign = 128; LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = ::APFloat::PPCDoubleDouble(); } - /// Flags for architecture specific defines. - typedef enum { -ArchDefineNone = 0, -ArchDefineName = 1 << 0, // is substituted
r334613 - [PowerPC] The __float128 type should only be available on Power9
Author: stefanp Date: Wed Jun 13 09:05:05 2018 New Revision: 334613 URL: http://llvm.org/viewvc/llvm-project?rev=334613=rev Log: [PowerPC] The __float128 type should only be available on Power9 Diasble the use of the type __float128 for PPC machines older than Power9. The use of -mfloat128 for PPC machine older than Power9 will result in an error. Differential Revision: https://reviews.llvm.org/D48088 Added: cfe/trunk/test/Driver/ppc-f128-support-check.c Modified: cfe/trunk/lib/Basic/Targets/PPC.cpp cfe/trunk/lib/Basic/Targets/PPC.h cfe/trunk/test/Preprocessor/init.c cfe/trunk/test/Sema/float128-ld-incompatibility.cpp Modified: cfe/trunk/lib/Basic/Targets/PPC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/PPC.cpp?rev=334613=334612=334613=diff == --- cfe/trunk/lib/Basic/Targets/PPC.cpp (original) +++ cfe/trunk/lib/Basic/Targets/PPC.cpp Wed Jun 13 09:05:05 2018 @@ -15,7 +15,6 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/MacroBuilder.h" #include "clang/Basic/TargetBuiltins.h" -#include "llvm/ADT/StringSwitch.h" using namespace clang; using namespace clang::targets; @@ -116,111 +115,37 @@ void PPCTargetInfo::getTargetDefines(con (getTriple().getOS() == llvm::Triple::Darwin && PointerWidth == 64)) Builder.defineMacro("__STRUCT_PARM_ALIGN__", "16"); - // CPU identification. - ArchDefineTypes defs = - (ArchDefineTypes)llvm::StringSwitch(CPU) - .Case("440", ArchDefineName) - .Case("450", ArchDefineName | ArchDefine440) - .Case("601", ArchDefineName) - .Case("602", ArchDefineName | ArchDefinePpcgr) - .Case("603", ArchDefineName | ArchDefinePpcgr) - .Case("603e", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) - .Case("603ev", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) - .Case("604", ArchDefineName | ArchDefinePpcgr) - .Case("604e", ArchDefineName | ArchDefine604 | ArchDefinePpcgr) - .Case("620", ArchDefineName | ArchDefinePpcgr) - .Case("630", ArchDefineName | ArchDefinePpcgr) - .Case("7400", ArchDefineName | ArchDefinePpcgr) - .Case("7450", ArchDefineName | ArchDefinePpcgr) - .Case("750", ArchDefineName | ArchDefinePpcgr) - .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("a2", ArchDefineA2) - .Case("a2q", ArchDefineName | ArchDefineA2 | ArchDefineA2q) - .Case("pwr3", ArchDefinePpcgr) - .Case("pwr4", ArchDefineName | ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr5", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr | -ArchDefinePpcsq) - .Case("pwr5x", ArchDefineName | ArchDefinePwr5 | ArchDefinePwr4 | - ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr6", ArchDefineName | ArchDefinePwr5x | ArchDefinePwr5 | -ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr6x", ArchDefineName | ArchDefinePwr6 | ArchDefinePwr5x | - ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("pwr7", ArchDefineName | ArchDefinePwr6x | ArchDefinePwr6 | -ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | -ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr8", ArchDefineName | ArchDefinePwr7 | ArchDefinePwr6x | -ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | -ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr9", ArchDefineName | ArchDefinePwr8 | ArchDefinePwr7 | -ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | -ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | -ArchDefinePpcsq) - .Case("power3", ArchDefinePpcgr) - .Case("power4", ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Case("power5", ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("power5x", ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | - ArchDefinePpcgr | ArchDefinePpcsq) - .Case("power6", ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | - ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("power6x", ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | - ArchDefinePwr5 | ArchDefinePwr4 | - ArchDefinePpcgr | ArchDefinePpcsq) - .Case("power7", ArchDefinePwr7 | ArchDefinePwr6x | ArchDefinePwr6 | -
r334612 - [libclang] Make c-index-test.c ISO C90 compliant.
Author: morehouse Date: Wed Jun 13 09:00:39 2018 New Revision: 334612 URL: http://llvm.org/viewvc/llvm-project?rev=334612=rev Log: [libclang] Make c-index-test.c ISO C90 compliant. Fixes a build bot breakage caused by r334593. Modified: cfe/trunk/tools/c-index-test/c-index-test.c Modified: cfe/trunk/tools/c-index-test/c-index-test.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=334612=334611=334612=diff == --- cfe/trunk/tools/c-index-test/c-index-test.c (original) +++ cfe/trunk/tools/c-index-test/c-index-test.c Wed Jun 13 09:00:39 2018 @@ -2304,6 +2304,7 @@ static void print_completion_result(CXTr CXString BriefComment; CXString Annotation; const char *BriefCommentCString; + unsigned i; fprintf(file, "%s:", clang_getCString(ks)); clang_disposeString(ks); @@ -2365,7 +2366,6 @@ static void print_completion_result(CXTr } clang_disposeString(BriefComment); - unsigned i; for (i = 0; i < clang_getCompletionNumFixIts(completion_results, index); ++i) { CXSourceRange correction_range; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46915: [Fixed Point Arithmetic] Fixed Point Precision Bits and Fixed Point Literals
ebevhan added inline comments. Comment at: lib/AST/ExprConstant.cpp:9437 + } + return Success(-Value, E); +} This looks very suspect to me as well... This might not respect padding on types whose sign bit is not the MSB, such as _Fract. The same goes for the overflow check above. I think it's quite important that we define the semantics of what padding bits should contain. Probably zeroes for unsigned types and a sexted sign bit for signed types. Repository: rC Clang https://reviews.llvm.org/D46915 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45679: [clang-tidy] Add ExprMutationAnalyzer, that analyzes whether an expression is mutated within a statement.
aaron.ballman reopened this revision. aaron.ballman added a comment. This revision is now accepted and ready to land. I had to revert due to failing tests. The revert was done in r334606 and this is an example of a failing bot: http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/builds/31500 Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D45679 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47935: [clangd] Boost completion score according to file proximity.
ioeric updated this revision to Diff 151172. ioeric added a comment. - Rebased. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D47935 Files: clangd/CodeComplete.cpp clangd/FindSymbols.cpp clangd/Quality.cpp clangd/Quality.h unittests/clangd/QualityTests.cpp unittests/clangd/TestFS.cpp unittests/clangd/URITests.cpp Index: unittests/clangd/URITests.cpp === --- unittests/clangd/URITests.cpp +++ unittests/clangd/URITests.cpp @@ -14,46 +14,20 @@ namespace clang { namespace clangd { + +// Force the unittest URI scheme to be linked, +extern volatile int UnittestSchemeAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest = +UnittestSchemeAnchorSource; + namespace { using ::testing::AllOf; MATCHER_P(Scheme, S, "") { return arg.scheme() == S; } MATCHER_P(Authority, A, "") { return arg.authority() == A; } MATCHER_P(Body, B, "") { return arg.body() == B; } -// Assume all files in the schema have a "test-root/" root directory, and the -// schema path is the relative path to the root directory. -// So the schema of "/some-dir/test-root/x/y/z" is "test:x/y/z". -class TestScheme : public URIScheme { -public: - static const char *Scheme; - - static const char *TestRoot; - - llvm::Expected - getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body, - llvm::StringRef HintPath) const override { -auto Pos = HintPath.find(TestRoot); -assert(Pos != llvm::StringRef::npos); -return (HintPath.substr(0, Pos + llvm::StringRef(TestRoot).size()) + Body) -.str(); - } - - llvm::Expected - uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override { -auto Pos = AbsolutePath.find(TestRoot); -assert(Pos != llvm::StringRef::npos); -return URI(Scheme, /*Authority=*/"", - AbsolutePath.substr(Pos + llvm::StringRef(TestRoot).size())); - } -}; - -const char *TestScheme::Scheme = "unittest"; -const char *TestScheme::TestRoot = "/test-root/"; - -static URISchemeRegistry::Add X(TestScheme::Scheme, "Test schema"); - std::string createOrDie(llvm::StringRef AbsolutePath, llvm::StringRef Scheme = "file") { auto Uri = URI::create(AbsolutePath, Scheme); Index: unittests/clangd/TestFS.cpp === --- unittests/clangd/TestFS.cpp +++ unittests/clangd/TestFS.cpp @@ -7,6 +7,7 @@ // //===--===// #include "TestFS.h" +#include "URI.h" #include "llvm/Support/Errc.h" #include "gtest/gtest.h" @@ -62,5 +63,50 @@ return Path.str(); } +// Assume all files in the schema have a "test-root/" root directory, and the +// schema path is the relative path to the root directory. +// So the schema of "/some-dir/test-root/x/y/z" is "test:x/y/z". +class TestScheme : public URIScheme { +public: + static const char *Scheme; + + static const char *TestRoot; + + llvm::Expected + getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body, + llvm::StringRef HintPath) const override { +auto Pos = HintPath.find(TestRoot); +assert(Pos != llvm::StringRef::npos); +return (HintPath.substr(0, Pos + llvm::StringRef(TestRoot).size()) + Body) +.str(); + } + + llvm::Expected + uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override { +auto Pos = AbsolutePath.find(TestRoot); +if (Pos == llvm::StringRef::npos) + return llvm::make_error( + llvm::Twine("Directory ") + TestRoot + " not found in path " + + AbsolutePath, + llvm::inconvertibleErrorCode()); + +return URI(Scheme, /*Authority=*/"", + AbsolutePath.substr(Pos + llvm::StringRef(TestRoot).size())); + } +}; + +const char *TestScheme::Scheme = "unittest"; +#ifdef _WIN32 +const char *TestScheme::TestRoot = "\\test-root\\"; +#else +const char *TestScheme::TestRoot = "/test-root/"; +#endif + +static URISchemeRegistry::Add X(TestScheme::Scheme, "Test schema"); + +// This anchor is used to force the linker to link in the generated object file +// and thus register the plugin. +volatile int UnittestSchemeAnchorSource = 0; + } // namespace clangd } // namespace clang Index: unittests/clangd/QualityTests.cpp === --- unittests/clangd/QualityTests.cpp +++ unittests/clangd/QualityTests.cpp @@ -18,12 +18,19 @@ //===--===// #include "Quality.h" +#include "TestFS.h" #include "TestTU.h" #include "gmock/gmock.h" #include "gtest/gtest.h" namespace clang { namespace clangd { + +// Force the unittest URI scheme to be linked, +extern volatile int UnittestSchemeAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest = +UnittestSchemeAnchorSource; + namespace { TEST(QualityTests,
[clang-tools-extra] r334606 - Reverting r334604 due to failing tests.
Author: aaronballman Date: Wed Jun 13 08:02:34 2018 New Revision: 334606 URL: http://llvm.org/viewvc/llvm-project?rev=334606=rev Log: Reverting r334604 due to failing tests. http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/builds/31500 Removed: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.h clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Modified: clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt clang-tools-extra/trunk/unittests/clang-tidy/CMakeLists.txt Modified: clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt?rev=334606=334605=334606=diff == --- clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt (original) +++ clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt Wed Jun 13 08:02:34 2018 @@ -3,7 +3,6 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyUtils ASTUtils.cpp DeclRefExprUtils.cpp - ExprMutationAnalyzer.cpp ExprSequence.cpp FixItHintUtils.cpp HeaderFileExtensionsUtils.cpp Removed: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp?rev=334605=auto == --- clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp (removed) @@ -1,261 +0,0 @@ -//===-- ExprMutationAnalyzer.cpp - clang-tidy -===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--===// -#include "ExprMutationAnalyzer.h" - -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "llvm/ADT/STLExtras.h" - -namespace clang { -namespace tidy { -namespace utils { -using namespace ast_matchers; - -namespace { - -AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) { - return llvm::is_contained(Node.capture_inits(), E); -} - -AST_MATCHER_P(CXXForRangeStmt, hasRangeStmt, - ast_matchers::internal::Matcher, InnerMatcher) { - const DeclStmt *const Range = Node.getRangeStmt(); - return InnerMatcher.matches(*Range, Finder, Builder); -} - -const ast_matchers::internal::VariadicDynCastAllOfMatcher -cxxTypeidExpr; - -AST_MATCHER(CXXTypeidExpr, isPotentiallyEvaluated) { - return Node.isPotentiallyEvaluated(); -} - -const ast_matchers::internal::VariadicDynCastAllOfMatcher -cxxNoexceptExpr; - -const ast_matchers::internal::VariadicDynCastAllOfMatcher -genericSelectionExpr; - -AST_MATCHER_P(GenericSelectionExpr, hasControllingExpr, - ast_matchers::internal::Matcher, InnerMatcher) { - return InnerMatcher.matches(*Node.getControllingExpr(), Finder, Builder); -} - -const auto nonConstReferenceType = [] { - return referenceType(pointee(unless(isConstQualified(; -}; - -} // namespace - -const Stmt *ExprMutationAnalyzer::findMutation(const Expr *Exp) { - const auto Memoized = Results.find(Exp); - if (Memoized != Results.end()) -return Memoized->second; - - if (isUnevaluated(Exp)) -return Results[Exp] = nullptr; - - for (const auto : {::findDirectMutation, - ::findMemberMutation, - ::findArrayElementMutation, - ::findCastMutation, - ::findRangeLoopMutation, - ::findReferenceMutation}) { -if (const Stmt *S = (this->*Finder)(Exp)) - return Results[Exp] = S; - } - - return Results[Exp] = nullptr; -} - -bool ExprMutationAnalyzer::isUnevaluated(const Expr *Exp) { - return selectFirst( - "expr", - match( - findAll( - expr(equalsNode(Exp), - anyOf( - // `Exp` is part of the underlying expression of - // decltype/typeof if it has an ancestor of - // typeLoc. - hasAncestor(typeLoc(unless( - hasAncestor(unaryExprOrTypeTraitExpr(), - hasAncestor(expr(anyOf( - // `UnaryExprOrTypeTraitExpr` is unevaluated - // unless it's sizeof on VLA. - unaryExprOrTypeTraitExpr(unless(sizeOfExpr( - hasArgumentOfType(variableArrayType(), - //
[PATCH] D47935: [clangd] Boost completion score according to file proximity.
ioeric added a comment. In https://reviews.llvm.org/D47935#1129987, @sammccall wrote: > Sorry for the delay on this change. There's a bunch of complexity in this > problem that I haven't seen how to slice through: > > 1. the signals needed seem like a weird fit for the Symbol*Signals structs > for some reason (maybe my misdesign) According to offline discussion, I added a structure `SymbolRelevanceContext` that captures per-query signals like proximity paths. Not sure about the name though. > 2. the inconsistency between how we do this for Sema and for Index results > has... only slightly good reasons The proximity scores for index and sema are now explicitly separated to make it easier to understand and debug. > 3. the URI vs filename thing is awkward > 4. with all this, the actual scoring still seems ad-hoc and is missing > important parts (main header, transitive includes) > > Not all your fault that the code reflects this, the problem is tangly. But > it's hard for me to reason about APIs or performance or layering. > > Looking at the last point (scoring model) because it seems the most > tractable. I think this is basically an edit distance problem? (We can call > the result "proximity", start at one, and multiply by <1, or call it > "distance" and start at 0 and add penalties, but it's equivalent). > 5. we're computing distances between files (glossing over URI-space vs > file-space) > 6. the roots are the main file, and maybe the matching header > 7. edits take us from a filepath to a related filepath: > - from a file to a header it `#include`s > - from a file to its parent directory > - from a parent directory to a child directory > - from a parent directory to a file in it > 8. the distance is the smallest sum-of-penalties for any path leading from > the root to the symbol > > What do you think of this model? > > > > **If** the model seems reasonable, then it suggests an approach of building > a one-per-query data structure that computes the needed edit-distance > recursively, memoizing results. `SymbolRelevanceResults` could store the > symbol path and a pointer to the edit-distance machine, and for debugging the > machine would know how to describe its configuration. URI/path mapping > wouldn't be a performance concern (I think) if the memoization captured it. I like how this model addresses the proximity for src/ and include/ setup. I think we could start with something simple and iterate, although I agree that we should strike for a design that would be easy to replace the proximity algorithm in the future. > Let's chat offline? Comment at: clangd/Quality.cpp:171 +/// "uri:///a/b/c" will be treated as /a/b/c +static float uriProximity(StringRef UX, StringRef UY) { + auto SchemeSplitX = UX.split(':'); sammccall wrote: > ioeric wrote: > > sammccall wrote: > > > This doesn't look quite right to me. > > > We can tune the details later, but in practice this seems like it's > > > *very* hard to get zero proximity, which is our neutral score - you need > > > to be 18 directories away? > > > > > > FWIW, fozzie appears to give an additive boost proportional to 5-up, > > > where up is the number of directories from the context you have to > > > traverse up from the context to get to a parent of the symbol. (There's > > > no penalty for down-traversals probably for implementation reasons, this > > > should be smaller than the up-traversal penalty I think) > > The numbers are guessed... definitely happy to tune. > > > We can tune the details later, but in practice this seems like it's > > > *very* hard to get zero proximity, which is our neutral score - you need > > > to be 18 directories away? > > It's 18 directories away if one file is in an ancestor directories of the > > other (i.e. only traverse up or down). If you need to traverse up and down, > > the penalty for each directory is 0.1, which takes 10 directories (up+down, > > so > > 5 up in average). I think it's useful to make this distinction because I > > think it's more likely for a file to use a header if it's in the file path. > > > > > > I'm not sure if we should use zero as the neutral score. For example, if a > > codebase has deep directory structure, most scores are probably going to be > > small; conversely, most scores would be relatively big. I think relative > > scores are more useful. > > > > > (There's no penalty for down-traversals probably for implementation > > > reasons, this should be smaller than the up-traversal penalty I think) > > Why do you think down-traversal should take less penalty? > > > > If you need to traverse up and down, the penalty for each directory is 0.1, > > which takes 10 directories (up+down, so 5 up in average). > I think you've halved twice there - it still seems to be 10, which is a lot. > > > I'm not sure if we should use zero as the neutral score. > Well, zero is currently the
[PATCH] D47935: [clangd] Boost completion score according to file proximity.
ioeric updated this revision to Diff 151169. ioeric added a comment. - Introduced a one-per-query structure for relevance signals; use multiplication for proximity; simplify tests a bit; separate index and sema proximity scores. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D47935 Files: clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/CodeComplete.cpp clangd/FindSymbols.cpp clangd/Quality.cpp clangd/Quality.h clangd/index/FileIndex.cpp clangd/index/FileIndex.h unittests/clangd/ClangdTests.cpp unittests/clangd/FileIndexTests.cpp unittests/clangd/QualityTests.cpp unittests/clangd/TestFS.cpp unittests/clangd/URITests.cpp Index: unittests/clangd/URITests.cpp === --- unittests/clangd/URITests.cpp +++ unittests/clangd/URITests.cpp @@ -14,46 +14,20 @@ namespace clang { namespace clangd { + +// Force the unittest URI scheme to be linked, +extern volatile int UnittestSchemeAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest = +UnittestSchemeAnchorSource; + namespace { using ::testing::AllOf; MATCHER_P(Scheme, S, "") { return arg.scheme() == S; } MATCHER_P(Authority, A, "") { return arg.authority() == A; } MATCHER_P(Body, B, "") { return arg.body() == B; } -// Assume all files in the schema have a "test-root/" root directory, and the -// schema path is the relative path to the root directory. -// So the schema of "/some-dir/test-root/x/y/z" is "test:x/y/z". -class TestScheme : public URIScheme { -public: - static const char *Scheme; - - static const char *TestRoot; - - llvm::Expected - getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body, - llvm::StringRef HintPath) const override { -auto Pos = HintPath.find(TestRoot); -assert(Pos != llvm::StringRef::npos); -return (HintPath.substr(0, Pos + llvm::StringRef(TestRoot).size()) + Body) -.str(); - } - - llvm::Expected - uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override { -auto Pos = AbsolutePath.find(TestRoot); -assert(Pos != llvm::StringRef::npos); -return URI(Scheme, /*Authority=*/"", - AbsolutePath.substr(Pos + llvm::StringRef(TestRoot).size())); - } -}; - -const char *TestScheme::Scheme = "unittest"; -const char *TestScheme::TestRoot = "/test-root/"; - -static URISchemeRegistry::Add X(TestScheme::Scheme, "Test schema"); - std::string createOrDie(llvm::StringRef AbsolutePath, llvm::StringRef Scheme = "file") { auto Uri = URI::create(AbsolutePath, Scheme); Index: unittests/clangd/TestFS.cpp === --- unittests/clangd/TestFS.cpp +++ unittests/clangd/TestFS.cpp @@ -7,6 +7,7 @@ // //===--===// #include "TestFS.h" +#include "URI.h" #include "llvm/Support/Errc.h" #include "gtest/gtest.h" @@ -62,5 +63,50 @@ return Path.str(); } +// Assume all files in the schema have a "test-root/" root directory, and the +// schema path is the relative path to the root directory. +// So the schema of "/some-dir/test-root/x/y/z" is "test:x/y/z". +class TestScheme : public URIScheme { +public: + static const char *Scheme; + + static const char *TestRoot; + + llvm::Expected + getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body, + llvm::StringRef HintPath) const override { +auto Pos = HintPath.find(TestRoot); +assert(Pos != llvm::StringRef::npos); +return (HintPath.substr(0, Pos + llvm::StringRef(TestRoot).size()) + Body) +.str(); + } + + llvm::Expected + uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override { +auto Pos = AbsolutePath.find(TestRoot); +if (Pos == llvm::StringRef::npos) + return llvm::make_error( + llvm::Twine("Directory ") + TestRoot + " not found in path " + + AbsolutePath, + llvm::inconvertibleErrorCode()); + +return URI(Scheme, /*Authority=*/"", + AbsolutePath.substr(Pos + llvm::StringRef(TestRoot).size())); + } +}; + +const char *TestScheme::Scheme = "unittest"; +#ifdef _WIN32 +const char *TestScheme::TestRoot = "\\test-root\\"; +#else +const char *TestScheme::TestRoot = "/test-root/"; +#endif + +static URISchemeRegistry::Add X(TestScheme::Scheme, "Test schema"); + +// This anchor is used to force the linker to link in the generated object file +// and thus register the plugin. +volatile int UnittestSchemeAnchorSource = 0; + } // namespace clangd } // namespace clang Index: unittests/clangd/QualityTests.cpp === --- unittests/clangd/QualityTests.cpp +++ unittests/clangd/QualityTests.cpp @@ -18,12 +18,19 @@ //===--===// #include "Quality.h" +#include "TestFS.h" #include "TestTU.h"
[PATCH] D47578: Do not enforce absolute path argv0 in windows
takuto.ikuta added a comment. Thank you! https://reviews.llvm.org/D47578 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48027: [analyzer] Improve `CallDescription` to handle c++ method.
MTC updated this revision to Diff 151166. MTC added a comment. - Use `hasName` matcher to match the qualified name. - Use the full name, like `std::basic_string::c_str` instead of `c_str` to match the `c_str` method in `DanglingInternalBufferChecker.cpp`. Repository: rC Clang https://reviews.llvm.org/D48027 Files: include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp lib/StaticAnalyzer/Core/CallEvent.cpp Index: lib/StaticAnalyzer/Core/CallEvent.cpp === --- lib/StaticAnalyzer/Core/CallEvent.cpp +++ lib/StaticAnalyzer/Core/CallEvent.cpp @@ -28,6 +28,7 @@ #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/ProgramPoint.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/CrossTU/CrossTranslationUnit.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" @@ -65,6 +66,7 @@ using namespace clang; using namespace ento; +using namespace clang::ast_matchers; QualType CallEvent::getResultType() const { ASTContext = getState()->getStateManager().getContext(); @@ -256,11 +258,24 @@ return false; if (!CD.IsLookupDone) { CD.IsLookupDone = true; -CD.II = ()->getStateManager().getContext().Idents.get(CD.FuncName); +CD.II = ()->getStateManager().getContext().Idents.get( +CD.getFunctionName()); } const IdentifierInfo *II = getCalleeIdentifier(); if (!II || II != CD.II) return false; + + const NamedDecl *ND = dyn_cast_or_null(getDecl()); + if (!ND) +return false; + + auto Matches = + match(namedDecl(hasName(CD.FuncName)).bind("match_qualified_name"), *ND, +LCtx->getAnalysisDeclContext()->getASTContext()); + + if (Matches.empty()) +return false; + return (CD.RequiredArgs == CallDescription::NoArgRequirement || CD.RequiredArgs == getNumArgs()); } Index: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp === --- lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp +++ lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp @@ -13,26 +13,28 @@ // //===--===// +#include "AllocationState.h" #include "ClangSACheckers.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include "AllocationState.h" +#include "llvm/ADT/SmallVector.h" using namespace clang; using namespace ento; namespace { class DanglingInternalBufferChecker : public Checker { - CallDescription CStrFn; + const llvm::SmallVector CStrFnFamily = { +{"std::basic_string::c_str"}, {"std::basic_string::c_str"}, +{"std::basic_string::c_str"}, +{"std::basic_string::c_str"}}; public: - DanglingInternalBufferChecker() : CStrFn("c_str") {} - /// Record the connection between the symbol returned by c_str() and the /// corresponding string object region in the ProgramState. Mark the symbol /// released if the string object is destroyed. @@ -65,7 +67,15 @@ ProgramStateRef State = C.getState(); - if (Call.isCalled(CStrFn)) { + auto isCStrFnFamilyCall = [&](const CallEvent ) -> bool { +for (auto CStrFn : CStrFnFamily) { + if (Call.isCalled(CStrFn)) +return true; +} +return false; + }; + + if (isCStrFnFamilyCall(Call)) { SVal RawPtr = Call.getReturnValue(); if (!RawPtr.isUnknown()) { State = State->set(TypedR, RawPtr.getAsSymbol()); Index: include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h === --- include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -79,6 +79,7 @@ mutable IdentifierInfo *II = nullptr; mutable bool IsLookupDone = false; + // Represent the function name or method name, like "X" or "a::b::X". StringRef FuncName; unsigned RequiredArgs; @@ -96,7 +97,11 @@ : FuncName(FuncName), RequiredArgs(RequiredArgs) {} /// Get the name of the function that this object matches. - StringRef getFunctionName() const { return FuncName; } + StringRef getFunctionName() const { +auto QualifierNamePair = FuncName.rsplit("::"); +return QualifierNamePair.second.empty() ? QualifierNamePair.first +: QualifierNamePair.second; + } }; template ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45679: [clang-tidy] Add ExprMutationAnalyzer, that analyzes whether an expression is mutated within a statement.
aaron.ballman closed this revision. aaron.ballman added a comment. I've commit in r334604 with one minor change -- I added an include for to the unit test so that `std::isspace()` would compile properly on all platforms. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D45679 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] r334604 - Add a new class to analyze whether an expression is mutated within a statement.
Author: aaronballman Date: Wed Jun 13 07:41:42 2018 New Revision: 334604 URL: http://llvm.org/viewvc/llvm-project?rev=334604=rev Log: Add a new class to analyze whether an expression is mutated within a statement. ExprMutationAnalyzer is a generally useful helper that can be used in different clang-tidy checks for checking whether a given expression is (potentially) mutated within a statement (typically the enclosing compound statement.) This is a more general and more powerful/accurate version of isOnlyUsedAsConst, which is used in ForRangeCopyCheck, UnnecessaryCopyInitialization. Patch by Shuai Wang Added: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.h clang-tools-extra/trunk/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp Modified: clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt clang-tools-extra/trunk/unittests/clang-tidy/CMakeLists.txt Modified: clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt?rev=334604=334603=334604=diff == --- clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt (original) +++ clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt Wed Jun 13 07:41:42 2018 @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyUtils ASTUtils.cpp DeclRefExprUtils.cpp + ExprMutationAnalyzer.cpp ExprSequence.cpp FixItHintUtils.cpp HeaderFileExtensionsUtils.cpp Added: clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp?rev=334604=auto == --- clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp (added) +++ clang-tools-extra/trunk/clang-tidy/utils/ExprMutationAnalyzer.cpp Wed Jun 13 07:41:42 2018 @@ -0,0 +1,261 @@ +//===-- ExprMutationAnalyzer.cpp - clang-tidy -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// +#include "ExprMutationAnalyzer.h" + +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "llvm/ADT/STLExtras.h" + +namespace clang { +namespace tidy { +namespace utils { +using namespace ast_matchers; + +namespace { + +AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) { + return llvm::is_contained(Node.capture_inits(), E); +} + +AST_MATCHER_P(CXXForRangeStmt, hasRangeStmt, + ast_matchers::internal::Matcher, InnerMatcher) { + const DeclStmt *const Range = Node.getRangeStmt(); + return InnerMatcher.matches(*Range, Finder, Builder); +} + +const ast_matchers::internal::VariadicDynCastAllOfMatcher +cxxTypeidExpr; + +AST_MATCHER(CXXTypeidExpr, isPotentiallyEvaluated) { + return Node.isPotentiallyEvaluated(); +} + +const ast_matchers::internal::VariadicDynCastAllOfMatcher +cxxNoexceptExpr; + +const ast_matchers::internal::VariadicDynCastAllOfMatcher +genericSelectionExpr; + +AST_MATCHER_P(GenericSelectionExpr, hasControllingExpr, + ast_matchers::internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getControllingExpr(), Finder, Builder); +} + +const auto nonConstReferenceType = [] { + return referenceType(pointee(unless(isConstQualified(; +}; + +} // namespace + +const Stmt *ExprMutationAnalyzer::findMutation(const Expr *Exp) { + const auto Memoized = Results.find(Exp); + if (Memoized != Results.end()) +return Memoized->second; + + if (isUnevaluated(Exp)) +return Results[Exp] = nullptr; + + for (const auto : {::findDirectMutation, + ::findMemberMutation, + ::findArrayElementMutation, + ::findCastMutation, + ::findRangeLoopMutation, + ::findReferenceMutation}) { +if (const Stmt *S = (this->*Finder)(Exp)) + return Results[Exp] = S; + } + + return Results[Exp] = nullptr; +} + +bool ExprMutationAnalyzer::isUnevaluated(const Expr *Exp) { + return selectFirst( + "expr", + match( + findAll( + expr(equalsNode(Exp), + anyOf( + // `Exp` is part of the underlying expression of + // decltype/typeof if it has an ancestor of + // typeLoc. + hasAncestor(typeLoc(unless( + hasAncestor(unaryExprOrTypeTraitExpr(), +
[PATCH] D47578: Do not enforce absolute path argv0 in windows
hans added a comment. In https://reviews.llvm.org/D47578#1127749, @takuto.ikuta wrote: > Rui-san, can I ask you to merge this? Committed here: http://llvm.org/viewvc/llvm-project?view=revision=334602 https://reviews.llvm.org/D47578 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits