diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp @@ -357,6 +357,8 @@ } if (const auto *DeclRef = Result.Nodes.getNodeAs("declRef")) { + if (DeclRef->refersToImplicitCapture()) + return; SourceRange Range = DeclRef->getNameInfo().getSourceRange(); addUsage(DeclRef->getDecl(), Range, Result.SourceManager); return; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp @@ -633,3 +633,24 @@ task ImplicitDeclTest(async_obj &a_object) { co_await a_object; // CHECK-MESSAGES-NOT: warning: invalid case style for local variable } + +// CHECK-MESSAGES: :[[@LINE+2]]:21: warning: invalid case style for parameter 'Param' +// CHECK-MESSAGES: :[[@LINE+1]]:32: warning: invalid case style for parameter 'Param2' +void LambdaTest(int Param, int Param2) { + (void)[Param]() { return Param; }; + (void)[&Param]() { return Param; }; + (void)[=]() { return Param; }; + (void)[&]() { return Param; }; + (void)[=]() { return Param + Param2; }; + (void)[=, &Param]() { return Param + Param2; }; + (void)[=, Param(Param)]() { return Param + Param2; }; + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for local variable 'Param' + // CHECK-FIXES: void LambdaTest(int a_param, int a_param2) { + // CHECK-FIXES-NEXT: (void)[a_param]() { return a_param; }; + // CHECK-FIXES-NEXT: (void)[&a_param]() { return a_param; }; + // CHECK-FIXES-NEXT: (void)[=]() { return a_param; }; + // CHECK-FIXES-NEXT: (void)[&]() { return a_param; }; + // CHECK-FIXES-NEXT: (void)[=]() { return a_param + a_param2; }; + // CHECK-FIXES-NEXT: (void)[=, &a_param]() { return a_param + a_param2; }; + // CHECK-FIXES-NEXT: (void)[=, param(a_param)]() { return param + a_param2; }; +} diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1416,6 +1416,14 @@ return DeclRefExprBits.RefersToEnclosingVariableOrCapture; } + bool refersToImplicitCapture() const { + return DeclRefExprBits.RefersToImplicitCapture; + } + + bool setRefersToImplicitCapture(bool V = true) { + return DeclRefExprBits.RefersToImplicitCapture = V; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -375,6 +375,7 @@ unsigned HadMultipleCandidates : 1; unsigned RefersToEnclosingVariableOrCapture : 1; unsigned NonOdrUseReason : 2; + unsigned RefersToImplicitCapture : 1; /// The location of the declaration name itself. SourceLocation Loc; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6673,6 +6673,8 @@ E->getValueKind(), ToFoundD, ToResInfo, E->isNonOdrUse()); if (E->hadMultipleCandidates()) ToE->setHadMultipleCandidates(true); + if (E->refersToImplicitCapture()) + ToE->setRefersToImplicitCapture(true); return ToE; } diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -389,6 +389,7 @@ DeclRefExprBits.HadMultipleCandidates = false; DeclRefExprBits.RefersToEnclosingVariableOrCapture = RefersToEnclosingVariableOrCapture; + DeclRefExprBits.RefersToImplicitCapture = false; DeclRefExprBits.NonOdrUseReason = NOUR; DeclRefExprBits.Loc = L; setDependence(computeDependence(this, Ctx)); @@ -415,6 +416,7 @@ = (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0; DeclRefExprBits.RefersToEnclosingVariableOrCapture = RefersToEnclosingVariableOrCapture; + DeclRefExprBits.RefersToImplicitCapture = false; DeclRefExprBits.NonOdrUseReason = NOUR; if (TemplateArgs) { auto Deps = TemplateArgumentDependence::None; diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -988,6 +988,8 @@ case NOUR_Constant: OS << " non_odr_use_constant"; break; case NOUR_Discarded: OS << " non_odr_use_discarded"; break; } + if (Node->refersToImplicitCapture()) + OS << " implicit_capture"; } void TextNodeDumper::VisitUnresolvedLookupExpr( diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1615,6 +1615,8 @@ return ExprError(); Expr *InitExpr = Init.get(); + if (Cap.isVariableCapture() && ImplicitCaptureLoc.isValid()) + cast(InitExpr)->setRefersToImplicitCapture(true); InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture( Name, Cap.getCaptureType(), Loc); InitializationKind InitKind = diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -597,6 +597,7 @@ E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record.readInt(); E->DeclRefExprBits.HadMultipleCandidates = Record.readInt(); E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt(); + E->DeclRefExprBits.RefersToImplicitCapture = Record.readInt(); E->DeclRefExprBits.NonOdrUseReason = Record.readInt(); unsigned NumTemplateArgs = 0; if (E->hasTemplateKWAndArgsInfo()) @@ -2809,12 +2810,14 @@ case EXPR_DECL_REF: S = DeclRefExpr::CreateEmpty( - Context, - /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], - /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 2], - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ? - Record[ASTStmtReader::NumExprFields + 6] : 0); + Context, + /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], + /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], + /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 2], + /*NumTemplateArgs=*/ + Record[ASTStmtReader::NumExprFields + 2] + ? Record[ASTStmtReader::NumExprFields + 7] + : 0); break; case EXPR_INTEGER_LITERAL: diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2281,6 +2281,8 @@ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates Abv->Add(BitCodeAbbrevOp(0)); // RefersToEnclosingVariableOrCapture + Abv->Add( + BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // RefersToImplicitCapture Abv->Add(BitCodeAbbrevOp(0)); // NonOdrUseReason Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -599,6 +599,7 @@ Record.push_back(E->hasTemplateKWAndArgsInfo()); Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->refersToEnclosingVariableOrCapture()); + Record.push_back(E->refersToImplicitCapture()); Record.push_back(E->isNonOdrUse()); if (E->hasTemplateKWAndArgsInfo()) {