diff options
| -rw-r--r-- | lib/Basic/Version.cpp | 2 | ||||
| -rw-r--r-- | lib/Sema/SemaDecl.cpp | 26 | ||||
| -rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 5 | ||||
| -rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 1 | ||||
| -rw-r--r-- | test/SemaCXX/unused.cpp | 50 | 
5 files changed, 73 insertions, 11 deletions
| diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp index 3fd322483392..2c569ff87d8a 100644 --- a/lib/Basic/Version.cpp +++ b/lib/Basic/Version.cpp @@ -36,7 +36,7 @@ std::string getClangRepositoryPath() {    // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us    // pick up a tag in an SVN export, for example. -  StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/branches/release_50/lib/Basic/Version.cpp $"); +  StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_501/final/lib/Basic/Version.cpp $");    if (URL.empty()) {      URL = SVNRepository.slice(SVNRepository.find(':'),                                SVNRepository.find("/lib/Basic")); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 692a77e2b62f..59c10128f908 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1603,7 +1603,24 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {    if (D->isInvalidDecl())      return false; -  if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>() || +  bool Referenced = false; +  if (auto *DD = dyn_cast<DecompositionDecl>(D)) { +    // For a decomposition declaration, warn if none of the bindings are +    // referenced, instead of if the variable itself is referenced (which +    // it is, by the bindings' expressions). +    for (auto *BD : DD->bindings()) { +      if (BD->isReferenced()) { +        Referenced = true; +        break; +      } +    } +  } else if (!D->getDeclName()) { +    return false; +  } else if (D->isReferenced() || D->isUsed()) { +    Referenced = true; +  } + +  if (Referenced || D->hasAttr<UnusedAttr>() ||        D->hasAttr<ObjCPreciseLifetimeAttr>())      return false; @@ -1726,7 +1743,7 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {    else      DiagID = diag::warn_unused_variable; -  Diag(D->getLocation(), DiagID) << D->getDeclName() << Hint; +  Diag(D->getLocation(), DiagID) << D << Hint;  }  static void CheckPoppedLabel(LabelDecl *L, Sema &S) { @@ -1756,8 +1773,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {      assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");      NamedDecl *D = cast<NamedDecl>(TmpD); -    if (!D->getDeclName()) continue; -      // Diagnose unused variables in this scope.      if (!S->hasUnrecoverableErrorOccurred()) {        DiagnoseUnusedDecl(D); @@ -1765,6 +1780,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {          DiagnoseUnusedNestedTypedefs(RD);      } +    if (!D->getDeclName()) continue; +      // If this was a forward reference to a label, verify it was defined.      if (LabelDecl *LD = dyn_cast<LabelDecl>(D))        CheckPoppedLabel(LD, *this); @@ -6155,7 +6172,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(    IdentifierInfo *II = Name.getAsIdentifierInfo();    if (D.isDecompositionDeclarator()) { -    AddToScope = false;      // Take the name of the first declarator as our name for diagnostic      // purposes.      auto &Decomp = D.getDecompositionDeclarator(); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index c05e5f020708..28323f365af7 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -826,7 +826,10 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,    NamedDecl *New =        ActOnVariableDeclarator(S, D, DC, TInfo, Previous,                                MultiTemplateParamsArg(), AddToScope, Bindings); -  CurContext->addHiddenDecl(New); +  if (AddToScope) { +    S->AddDecl(New); +    CurContext->addHiddenDecl(New); +  }    if (isInOpenMPDeclareTargetContext())      checkDeclIsAllowedInOpenMPTarget(nullptr, New); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6fee23aa8bc1..4a26efcc9431 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -677,6 +677,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {  Decl *TemplateDeclInstantiator::VisitBindingDecl(BindingDecl *D) {    auto *NewBD = BindingDecl::Create(SemaRef.Context, Owner, D->getLocation(),                                      D->getIdentifier()); +  NewBD->setReferenced(D->isReferenced());    SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewBD);    return NewBD;  } diff --git a/test/SemaCXX/unused.cpp b/test/SemaCXX/unused.cpp index 09a179e7bb85..ba9ab2363b06 100644 --- a/test/SemaCXX/unused.cpp +++ b/test/SemaCXX/unused.cpp @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wunused %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -Wunused %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wunused %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wunused %s  // PR4103 : Make sure we don't get a bogus unused expression warning  namespace PR4103 { @@ -8,7 +9,7 @@ namespace PR4103 {      char foo;    };    class APSInt : public APInt { -    char bar; +    char bar; // expected-warning {{private field 'bar' is not used}}    public:      APSInt &operator=(const APSInt &RHS);    }; @@ -69,3 +70,44 @@ namespace UnresolvedLookup {      }    };  } + +#if __cplusplus >= 201703L +namespace PR33839 { +  void a() { +    struct X { int a, b; } x; +    auto [a, b] = x; // expected-warning {{unused variable '[a, b]'}} +    auto [c, d] = x; +    (void)d; +  } + +  template<typename T> void f() { +    struct A { int n; } a[1]; +    for (auto [x] : a) { +      (void)x; +    } +    auto [y] = a[0]; // expected-warning {{unused}} +  } +  template<bool b> void g() { +    struct A { int n; } a[1]; +    for (auto [x] : a) { +      if constexpr (b) +        (void)x; +    } + +    auto [y] = a[0]; +    if constexpr (b) +      (void)y; // ok, even when b == false +  } +  template<typename T> void h() { +    struct A { int n; } a[1]; +    for (auto [x] : a) { // expected-warning {{unused variable '[x]'}} +    } +  } +  void use() {  +    f<int>(); // expected-note {{instantiation of}} +    g<true>(); +    g<false>(); +    h<int>(); // expected-note {{instantiation of}} +  } +} +#endif | 
