diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -229,6 +229,11 @@ 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 --- 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 @@ // 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 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -202,6 +202,10 @@ 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 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -63,8 +63,9 @@ // 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 --- a/clang/test/AST/ast-dump-overloaded-operators.cpp +++ b/clang/test/AST/ast-dump-overloaded-operators.cpp @@ -24,21 +24,44 @@ // 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 --- a/clang/test/Index/annotate-operator-call-expr.cpp +++ b/clang/test/Index/annotate-operator-call-expr.cpp @@ -17,68 +17,68 @@ // 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 --- a/clang/test/Index/cursor-ref-names.cpp +++ b/clang/test/Index/cursor-ref-names.cpp @@ -33,9 +33,9 @@ // 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 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -4675,6 +4675,9 @@ 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) {