From: Danny Mösch Date: Sun, 17 Jul 2022 19:28:36 +0000 (+0200) Subject: [clang] Pass FoundDecl to DeclRefExpr creator for operator overloads X-Git-Tag: upstream/15.0.7~359 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4e94f6653150511de434fa7e29b684ae7f0e52b6;p=platform%2Fupstream%2Fllvm.git [clang] Pass FoundDecl to DeclRefExpr creator for operator overloads Without the "found declaration" it is later not possible to know where the operator declaration was brought into the scope calling it. The initial motivation for this fix came from #55095. However, this also has an influence on `clang -ast-dump` which now prints a `UsingShadow` attribute for operators only visible through `using` statements. Also, clangd now correctly references the `using` statement instead of the operator directly. Reviewed By: shafik Differential Revision: https://reviews.llvm.org/D129973 --- diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 3090f4a..75c7f44 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -229,6 +229,11 @@ Changes in existing checks where invalid parameters were implicitly being treated as being unused. This fixes `Issue 56152 `_. +- Fixed false positives in :doc:`misc-unused-using-decls + ` where `using` statements bringing + operators into the scope where incorrectly marked as unused. + This fixes `issue 55095 `_. + - Fixed a false positive in :doc:`modernize-deprecated-headers ` involving including C header files from C++ files wrapped by ``extern "C" { ... }`` blocks. diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.cpp index 63bf34c..0d08edb 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.cpp @@ -210,3 +210,14 @@ template class U> class Bar {}; // We used to report Q unsued, because we only checked the first template // argument. Bar *bar; + +namespace internal { + struct S {}; + int operator+(S s1, S s2); +} + +// Make sure this statement is not reported as unused. +using internal::operator+; +using internal::S; + +int j() { return S() + S(); } diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8b44e90..74505dd 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -202,6 +202,10 @@ Bug Fixes considered to have one positive bit in order to represent the underlying value. This effects whether we consider the store of the value one to be well defined. +- An operator introduced to the scope via a `using` statement now correctly references this + statement in clangd (hover over the symbol, jump to definition) as well as in the AST dump. + This also fixes `issue 55095 `_ as a + side-effect. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 5dc0aad..d72cc33 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -63,8 +63,9 @@ static ExprResult CreateFunctionRefExpr( // being used. if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc)) return ExprError(); - DeclRefExpr *DRE = new (S.Context) - DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); + DeclRefExpr *DRE = + DeclRefExpr::Create(S.Context, Fn->getQualifierLoc(), SourceLocation(), + Fn, false, Loc, Fn->getType(), VK_LValue, FoundDecl); if (HadMultipleCandidates) DRE->setHadMultipleCandidates(true); diff --git a/clang/test/AST/ast-dump-overloaded-operators.cpp b/clang/test/AST/ast-dump-overloaded-operators.cpp index 639a0d9..0f89a42 100644 --- a/clang/test/AST/ast-dump-overloaded-operators.cpp +++ b/clang/test/AST/ast-dump-overloaded-operators.cpp @@ -24,21 +24,44 @@ void test() { // CHECK-NEXT: |-FunctionDecl {{.*}} col:6{{( imported)?}} used operator, 'void (E, E)' // CHECK-NEXT: | |-ParmVarDecl {{.*}} col:17{{( imported)?}} 'E' // CHECK-NEXT: | `-ParmVarDecl {{.*}} col:19{{( imported)?}} 'E' -// CHECK-NEXT: `-FunctionDecl {{.*}} line:14:6{{( imported)?}} test 'void ()' -// CHECK-NEXT: `-CompoundStmt {{.*}} -// CHECK-NEXT: |-DeclStmt {{.*}} -// CHECK-NEXT: | `-VarDecl {{.*}} col:5{{( imported)?}} used e 'E' -// CHECK-NEXT: |-CXXOperatorCallExpr {{.*}} 'void' '+' -// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' -// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator+' 'void (E, E)' -// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'E' -// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' -// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'E' -// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' -// CHECK-NEXT: `-CXXOperatorCallExpr {{.*}} 'void' ',' -// CHECK-NEXT: |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' -// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator,' 'void (E, E)' -// CHECK-NEXT: |-ImplicitCastExpr {{.*}} 'E' -// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' -// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'E' -// CHECK-NEXT: `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' +// CHECK-NEXT: |-FunctionDecl {{.*}} line:14:6{{( imported)?}} test 'void ()' +// CHECK-NEXT: | `-CompoundStmt {{.*}} +// CHECK-NEXT: | |-DeclStmt {{.*}} +// CHECK-NEXT: | | `-VarDecl {{.*}} col:5{{( imported)?}} used e 'E' +// CHECK-NEXT: | |-CXXOperatorCallExpr {{.*}} 'void' '+' +// CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' +// CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator+' 'void (E, E)' +// CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'E' +// CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' +// CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'E' +// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' +// CHECK-NEXT: | `-CXXOperatorCallExpr {{.*}} 'void' ',' +// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' +// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator,' 'void (E, E)' +// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'E' +// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' +// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'E' +// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' + +namespace a { + void operator-(E, E); +} + +using a::operator-; + +void f() { + E() - E(); +} +// CHECK: |-NamespaceDecl {{.*}} line:46:11{{( imported )?}} a +// CHECK-NEXT: | `-FunctionDecl {{.*}} col:8{{( imported)?}} used operator- 'void (E, E)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} col:19{{( imported)?}} 'E' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} col:22{{( imported)?}} 'E' +// CHECK-NEXT: |-UsingDecl {{.*}} col:10{{( imported)?}} a::operator- +// CHECK-NEXT: |-UsingShadowDecl {{.*}} col:10{{( imported)?}} implicit Function {{.*}} 'operator-' 'void (E, E)' +// CHECK-NEXT: `-FunctionDecl {{.*}} line:52:6{{( imported)?}} f 'void ()' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: `-CXXOperatorCallExpr {{.*}} 'void' '-' +// CHECK-NEXT: |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' +// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator-' 'void (E, E)' (UsingShadow {{.*}} 'operator-') +// CHECK-NEXT: |-CXXScalarValueInitExpr {{.*}} 'E' +// CHECK-NEXT: `-CXXScalarValueInitExpr {{.*}} 'E' diff --git a/clang/test/Index/annotate-operator-call-expr.cpp b/clang/test/Index/annotate-operator-call-expr.cpp index facb841..3da2ec7 100644 --- a/clang/test/Index/annotate-operator-call-expr.cpp +++ b/clang/test/Index/annotate-operator-call-expr.cpp @@ -17,68 +17,68 @@ void testFoo(Foo foo, int index) { // RUN: c-index-test -test-annotate-tokens=%s:7:1:7:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK1 // CHECK1: Identifier: "foo" [7:3 - 7:6] DeclRefExpr=foo:6:18 -// CHECK1: Punctuation: "(" [7:6 - 7:7] DeclRefExpr=operator():3:7 RefName=[7:6 - 7:7] RefName=[7:7 - 7:8] -// CHECK1: Punctuation: ")" [7:7 - 7:8] DeclRefExpr=operator():3:7 RefName=[7:6 - 7:7] RefName=[7:7 - 7:8] +// CHECK1: Punctuation: "(" [7:6 - 7:7] CallExpr=operator():3:7 +// CHECK1: Punctuation: ")" [7:7 - 7:8] CallExpr=operator():3:7 // CHECK1: Punctuation: ";" [7:8 - 7:9] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:8:1:8:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK2 -// CHECK2: Punctuation: "(" [8:6 - 8:7] DeclRefExpr=operator():3:7 RefName=[8:6 - 8:7] RefName=[8:12 - 8:13] +// CHECK2: Punctuation: "(" [8:6 - 8:7] CallExpr=operator():3:7 // CHECK2: Identifier: "index" [8:7 - 8:12] DeclRefExpr=index:6:27 -// CHECK2: Punctuation: ")" [8:12 - 8:13] DeclRefExpr=operator():3:7 RefName=[8:6 - 8:7] RefName=[8:12 - 8:13] +// CHECK2: Punctuation: ")" [8:12 - 8:13] CallExpr=operator():3:7 // CHECK2: Punctuation: ";" [8:13 - 8:14] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:10:1:10:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK3 // CHECK3: Identifier: "foo" [10:3 - 10:6] DeclRefExpr=foo:6:18 -// CHECK3: Punctuation: "[" [10:6 - 10:7] DeclRefExpr=operator[]:2:7 RefName=[10:6 - 10:7] RefName=[10:12 - 10:13] +// CHECK3: Punctuation: "[" [10:6 - 10:7] CallExpr=operator[]:2:7 // CHECK3: Identifier: "index" [10:7 - 10:12] DeclRefExpr=index:6:27 -// CHECK3: Punctuation: "]" [10:12 - 10:13] DeclRefExpr=operator[]:2:7 RefName=[10:6 - 10:7] RefName=[10:12 - 10:13] +// CHECK3: Punctuation: "]" [10:12 - 10:13] CallExpr=operator[]:2:7 // CHECK3: Punctuation: ";" [10:13 - 10:14] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:11:1:11:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK4 // CHECK4: Identifier: "foo" [11:3 - 11:6] DeclRefExpr=foo:6:18 -// CHECK4: Punctuation: "[" [11:6 - 11:7] DeclRefExpr=operator[]:2:7 RefName=[11:6 - 11:7] RefName=[11:20 - 11:21] +// CHECK4: Punctuation: "[" [11:6 - 11:7] CallExpr=operator[]:2:7 // CHECK4: Identifier: "index" [11:7 - 11:12] DeclRefExpr=index:6:27 // CHECK4: Punctuation: "+" [11:13 - 11:14] BinaryOperator= // CHECK4: Identifier: "index" [11:15 - 11:20] DeclRefExpr=index:6:27 -// CHECK4: Punctuation: "]" [11:20 - 11:21] DeclRefExpr=operator[]:2:7 RefName=[11:6 - 11:7] RefName=[11:20 - 11:21] +// CHECK4: Punctuation: "]" [11:20 - 11:21] CallExpr=operator[]:2:7 // CHECK4: Punctuation: ";" [11:21 - 11:22] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:13:1:13:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK5 // CHECK5: Identifier: "foo" [13:3 - 13:6] DeclRefExpr=foo:6:18 -// CHECK5: Punctuation: "[" [13:6 - 13:7] DeclRefExpr=operator[]:2:7 RefName=[13:6 - 13:7] RefName=[13:17 - 13:18] +// CHECK5: Punctuation: "[" [13:6 - 13:7] CallExpr=operator[]:2:7 // CHECK5: Identifier: "foo" [13:7 - 13:10] DeclRefExpr=foo:6:18 -// CHECK5: Punctuation: "[" [13:10 - 13:11] DeclRefExpr=operator[]:2:7 RefName=[13:10 - 13:11] RefName=[13:16 - 13:17] +// CHECK5: Punctuation: "[" [13:10 - 13:11] CallExpr=operator[]:2:7 // CHECK5: Identifier: "index" [13:11 - 13:16] DeclRefExpr=index:6:27 -// CHECK5: Punctuation: "]" [13:16 - 13:17] DeclRefExpr=operator[]:2:7 RefName=[13:10 - 13:11] RefName=[13:16 - 13:17] -// CHECK5: Punctuation: "]" [13:17 - 13:18] DeclRefExpr=operator[]:2:7 RefName=[13:6 - 13:7] RefName=[13:17 - 13:18] +// CHECK5: Punctuation: "]" [13:16 - 13:17] CallExpr=operator[]:2:7 +// CHECK5: Punctuation: "]" [13:17 - 13:18] CallExpr=operator[]:2:7 // CHECK5: Punctuation: ";" [13:18 - 13:19] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:14:1:14:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK6 // CHECK6: Identifier: "foo" [14:3 - 14:6] DeclRefExpr=foo:6:18 -// CHECK6: Punctuation: "[" [14:6 - 14:7] DeclRefExpr=operator[]:2:7 RefName=[14:6 - 14:7] RefName=[14:25 - 14:26] +// CHECK6: Punctuation: "[" [14:6 - 14:7] CallExpr=operator[]:2:7 // CHECK6: Identifier: "foo" [14:7 - 14:10] DeclRefExpr=foo:6:18 -// CHECK6: Punctuation: "(" [14:10 - 14:11] DeclRefExpr=operator():3:7 RefName=[14:10 - 14:11] RefName=[14:11 - 14:12] -// CHECK6: Punctuation: ")" [14:11 - 14:12] DeclRefExpr=operator():3:7 RefName=[14:10 - 14:11] RefName=[14:11 - 14:12] +// CHECK6: Punctuation: "(" [14:10 - 14:11] CallExpr=operator():3:7 +// CHECK6: Punctuation: ")" [14:11 - 14:12] CallExpr=operator():3:7 // CHECK6: Punctuation: "+" [14:13 - 14:14] BinaryOperator= // CHECK6: Identifier: "foo" [14:15 - 14:18] DeclRefExpr=foo:6:18 -// CHECK6: Punctuation: "[" [14:18 - 14:19] DeclRefExpr=operator[]:2:7 RefName=[14:18 - 14:19] RefName=[14:24 - 14:25] -// CHECK6: Identifier: "index" [14:19 - 14:24] DeclRefExpr=operator[]:2:7 RefName=[14:6 - 14:7] RefName=[14:25 - 14:26] -// CHECK6: Punctuation: "]" [14:24 - 14:25] DeclRefExpr=operator[]:2:7 RefName=[14:18 - 14:19] RefName=[14:24 - 14:25] -// CHECK6: Punctuation: "]" [14:25 - 14:26] DeclRefExpr=operator[]:2:7 RefName=[14:6 - 14:7] RefName=[14:25 - 14:26] +// CHECK6: Punctuation: "[" [14:18 - 14:19] CallExpr=operator[]:2:7 +// CHECK6: Identifier: "index" [14:19 - 14:24] DeclRefExpr=index:6:27 +// CHECK6: Punctuation: "]" [14:24 - 14:25] CallExpr=operator[]:2:7 +// CHECK6: Punctuation: "]" [14:25 - 14:26] CallExpr=operator[]:2:7 // CHECK6: Punctuation: ";" [14:26 - 14:27] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:15:1:15:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK7 // CHECK7: Identifier: "foo" [15:3 - 15:6] DeclRefExpr=foo:6:18 -// CHECK7: Punctuation: "[" [15:6 - 15:7] DeclRefExpr=operator[]:2:7 RefName=[15:6 - 15:7] RefName=[15:30 - 15:31] +// CHECK7: Punctuation: "[" [15:6 - 15:7] CallExpr=operator[]:2:7 // CHECK7: Identifier: "foo" [15:7 - 15:10] DeclRefExpr=foo:6:18 -// CHECK7: Punctuation: "(" [15:10 - 15:11] DeclRefExpr=operator():3:7 RefName=[15:10 - 15:11] RefName=[15:16 - 15:17] +// CHECK7: Punctuation: "(" [15:10 - 15:11] CallExpr=operator():3:7 // CHECK7: Identifier: "index" [15:11 - 15:16] DeclRefExpr=index:6:27 -// CHECK7: Punctuation: ")" [15:16 - 15:17] DeclRefExpr=operator():3:7 RefName=[15:10 - 15:11] RefName=[15:16 - 15:17] +// CHECK7: Punctuation: ")" [15:16 - 15:17] CallExpr=operator():3:7 // CHECK7: Punctuation: "+" [15:18 - 15:19] BinaryOperator= // CHECK7: Identifier: "foo" [15:20 - 15:23] DeclRefExpr=foo:6:18 -// CHECK7: Punctuation: "[" [15:23 - 15:24] DeclRefExpr=operator[]:2:7 RefName=[15:23 - 15:24] RefName=[15:29 - 15:30] +// CHECK7: Punctuation: "[" [15:23 - 15:24] CallExpr=operator[]:2:7 // CHECK7: Identifier: "index" [15:24 - 15:29] DeclRefExpr=index:6:27 -// CHECK7: Punctuation: "]" [15:29 - 15:30] DeclRefExpr=operator[]:2:7 RefName=[15:23 - 15:24] RefName=[15:29 - 15:30] -// CHECK7: Punctuation: "]" [15:30 - 15:31] DeclRefExpr=operator[]:2:7 RefName=[15:6 - 15:7] RefName=[15:30 - 15:31] +// CHECK7: Punctuation: "]" [15:29 - 15:30] CallExpr=operator[]:2:7 +// CHECK7: Punctuation: "]" [15:30 - 15:31] CallExpr=operator[]:2:7 // CHECK7: Punctuation: ";" [15:31 - 15:32] CompoundStmt= diff --git a/clang/test/Index/cursor-ref-names.cpp b/clang/test/Index/cursor-ref-names.cpp index 26174bc..e34c65e 100644 --- a/clang/test/Index/cursor-ref-names.cpp +++ b/clang/test/Index/cursor-ref-names.cpp @@ -33,9 +33,9 @@ int main() // CHECK: cursor-ref-names.cpp:18:5: CallExpr=func:8:10 Extent=[18:5 - 18:16] // CHECK: cursor-ref-names.cpp:18:10: MemberRefExpr=func:8:10 SingleRefName=[18:10 - 18:14] RefName=[18:10 - 18:14] Extent=[18:5 - 18:14] // CHECK: cursor-ref-names.cpp:18:5: DeclRefExpr=inst:17:9 Extent=[18:5 - 18:9] -// CHECK: cursor-ref-names.cpp:19:5: CallExpr=operator[]:4:9 SingleRefName=[19:9 - 19:12] RefName=[19:9 - 19:10] RefName=[19:11 - 19:12] Extent=[19:5 - 19:12] +// CHECK: cursor-ref-names.cpp:19:5: CallExpr=operator[]:4:9 Extent=[19:5 - 19:12] // CHECK: cursor-ref-names.cpp:19:5: DeclRefExpr=inst:17:9 Extent=[19:5 - 19:9] -// CHECK: cursor-ref-names.cpp:19:9: DeclRefExpr=operator[]:4:9 RefName=[19:9 - 19:10] RefName=[19:11 - 19:12] Extent=[19:9 - 19:12] +// CHECK: cursor-ref-names.cpp:19:9: DeclRefExpr=operator[]:4:9 Extent=[19:9 - 19:10] // CHECK: cursor-ref-names.cpp:20:5: CallExpr=operator[]:4:9 Extent=[20:5 - 20:23] // CHECK: cursor-ref-names.cpp:20:10: MemberRefExpr=operator[]:4:9 SingleRefName=[20:10 - 20:20] RefName=[20:10 - 20:18] RefName=[20:18 - 20:19] RefName=[20:19 - 20:20] Extent=[20:5 - 20:20] // CHECK: cursor-ref-names.cpp:20:5: DeclRefExpr=inst:17:9 Extent=[20:5 - 20:9] diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 8b3881a..e5a9447 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -4675,6 +4675,9 @@ TEST(UsingDeclaration, ThroughUsingDeclaration) { EXPECT_TRUE(notMatches( "namespace a { void f(); } using a::f; void g() { a::f(); }", declRefExpr(throughUsingDecl(anything())))); + EXPECT_TRUE(matches("struct S {}; namespace a { int operator+(S s1, S s2); } " + "using a::operator+; int g() { return S() + S(); }", + declRefExpr(throughUsingDecl(anything())))); } TEST(SingleDecl, IsSingleDecl) {