Skip to content

Commit 9d10172

Browse files
authored
1 parent 2369a54 commit 9d10172

File tree

9 files changed

+3
-813
lines changed

9 files changed

+3
-813
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -716,9 +716,6 @@ Improvements to Clang's diagnostics
716716

717717
- Clang now diagnoses integer constant expressions that are folded to a constant value as an extension in more circumstances. Fixes #GH59863
718718

719-
- Clang now diagnoses missing format attributes for non-template functions and
720-
class/struct/union members. Fixes #GH60718
721-
722719
Improvements to Clang's time-trace
723720
----------------------------------
724721

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ def MainReturnType : DiagGroup<"main-return-type">;
525525
def MaxUnsignedZero : DiagGroup<"max-unsigned-zero">;
526526
def MissingBraces : DiagGroup<"missing-braces">;
527527
def MissingDeclarations: DiagGroup<"missing-declarations">;
528+
def : DiagGroup<"missing-format-attribute">;
528529
def MissingIncludeDirs : DiagGroup<"missing-include-dirs">;
529530
def MissingNoreturn : DiagGroup<"missing-noreturn">;
530531
def MultiChar : DiagGroup<"multichar">;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,9 +1031,6 @@ def err_opencl_invalid_param : Error<
10311031
def err_opencl_invalid_return : Error<
10321032
"declaring function return value of type %0 is not allowed %select{; did you forget * ?|}1">;
10331033
def warn_enum_value_overflow : Warning<"overflow in enumeration value">;
1034-
def warn_missing_format_attribute : Warning<
1035-
"diagnostic behavior may be improved by adding the %0 format attribute to the declaration of %1">,
1036-
InGroup<DiagGroup<"missing-format-attribute">>, DefaultIgnore;
10371034
def warn_pragma_options_align_reset_failed : Warning<
10381035
"#pragma options align=reset failed: %0">,
10391036
InGroup<IgnoredPragmas>;

clang/include/clang/Sema/Attr.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,6 @@ inline bool isInstanceMethod(const Decl *D) {
123123
return false;
124124
}
125125

126-
inline bool checkIfMethodHasImplicitObjectParameter(const Decl *D) {
127-
if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
128-
return MethodDecl->isInstance() &&
129-
!MethodDecl->hasCXXExplicitFunctionObjectParameter();
130-
return false;
131-
}
132-
133126
/// Diagnose mutually exclusive attributes when present on a given
134127
/// declaration. Returns true if diagnosed.
135128
template <typename AttrTy>

clang/include/clang/Sema/Sema.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4594,10 +4594,6 @@ class Sema final : public SemaBase {
45944594

45954595
enum class RetainOwnershipKind { NS, CF, OS };
45964596

4597-
void DiagnoseMissingFormatAttributes(Stmt *Body, const FunctionDecl *FDecl);
4598-
std::vector<FormatAttr *>
4599-
GetMissingFormatAttributes(Stmt *Body, const FunctionDecl *FDecl);
4600-
46014597
UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
46024598
StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
46034599

clang/lib/Sema/SemaDecl.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15934,8 +15934,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
1593415934
}
1593515935
}
1593615936

15937-
DiagnoseMissingFormatAttributes(Body, FD);
15938-
1593915937
// We might not have found a prototype because we didn't wish to warn on
1594015938
// the lack of a missing prototype. Try again without the checks for
1594115939
// whether we want to warn on the missing prototype.

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 2 additions & 217 deletions
Original file line numberDiff line numberDiff line change
@@ -3508,7 +3508,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
35083508

35093509
// In C++ the implicit 'this' function parameter also counts, and they are
35103510
// counted from one.
3511-
bool HasImplicitThisParam = checkIfMethodHasImplicitObjectParameter(D);
3511+
bool HasImplicitThisParam = isInstanceMethod(D);
35123512
unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
35133513

35143514
IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
@@ -3621,7 +3621,7 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
36213621
return;
36223622
}
36233623

3624-
bool HasImplicitThisParam = checkIfMethodHasImplicitObjectParameter(D);
3624+
bool HasImplicitThisParam = isInstanceMethod(D);
36253625
int32_t NumArgs = getFunctionOrMethodNumParams(D);
36263626

36273627
FunctionDecl *FD = D->getAsFunction();
@@ -5320,221 +5320,6 @@ static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
53205320
D->addAttr(::new (S.Context) PreferredTypeAttr(S.Context, AL, ParmTSI));
53215321
}
53225322

5323-
// This function is called only if function call is not inside template body.
5324-
// TODO: Add call for function calls inside template body.
5325-
// Emit warnings if parent function misses format attributes.
5326-
void Sema::DiagnoseMissingFormatAttributes(Stmt *Body,
5327-
const FunctionDecl *FDecl) {
5328-
assert(FDecl);
5329-
5330-
// If there are no function body, exit.
5331-
if (!Body)
5332-
return;
5333-
5334-
// Get missing format attributes
5335-
std::vector<FormatAttr *> MissingFormatAttributes =
5336-
GetMissingFormatAttributes(Body, FDecl);
5337-
if (MissingFormatAttributes.empty())
5338-
return;
5339-
5340-
// Check if there are more than one format type found. In that case do not
5341-
// emit diagnostic.
5342-
const FormatAttr *FirstAttr = MissingFormatAttributes[0];
5343-
if (llvm::any_of(MissingFormatAttributes, [&](const FormatAttr *Attr) {
5344-
return FirstAttr->getType() != Attr->getType();
5345-
}))
5346-
return;
5347-
5348-
for (const FormatAttr *FA : MissingFormatAttributes) {
5349-
// If format index and first-to-check argument index are negative, it means
5350-
// that this attribute is only saved for multiple format types checking.
5351-
if (FA->getFormatIdx() < 0 || FA->getFirstArg() < 0)
5352-
continue;
5353-
5354-
// Emit diagnostic
5355-
SourceLocation Loc = FDecl->getLocation();
5356-
Diag(Loc, diag::warn_missing_format_attribute)
5357-
<< FA->getType() << FDecl
5358-
<< FixItHint::CreateInsertion(Loc,
5359-
(llvm::Twine("__attribute__((format(") +
5360-
FA->getType()->getName() + ", " +
5361-
llvm::Twine(FA->getFormatIdx()) + ", " +
5362-
llvm::Twine(FA->getFirstArg()) + ")))")
5363-
.str());
5364-
}
5365-
}
5366-
5367-
// Returns vector of format attributes. There are no two attributes with same
5368-
// arguments in returning vector. There can be attributes that effectivelly only
5369-
// store information about format type.
5370-
std::vector<FormatAttr *>
5371-
Sema::GetMissingFormatAttributes(Stmt *Body, const FunctionDecl *FDecl) {
5372-
unsigned int FunctionFormatArgumentIndexOffset =
5373-
checkIfMethodHasImplicitObjectParameter(FDecl) ? 2 : 1;
5374-
5375-
std::vector<FormatAttr *> MissingAttributes;
5376-
5377-
// Iterate over body statements.
5378-
for (auto *Child : Body->children()) {
5379-
// If child statement is compound statement, recursively get missing
5380-
// attributes.
5381-
if (dyn_cast_or_null<CompoundStmt>(Child)) {
5382-
std::vector<FormatAttr *> CompoundStmtMissingAttributes =
5383-
GetMissingFormatAttributes(Child, FDecl);
5384-
5385-
// If there are already missing attributes with same arguments, do not add
5386-
// duplicates.
5387-
for (FormatAttr *FA : CompoundStmtMissingAttributes) {
5388-
if (!llvm::any_of(MissingAttributes, [&](const FormatAttr *Attr) {
5389-
return FA->getType() == Attr->getType() &&
5390-
FA->getFormatIdx() == Attr->getFormatIdx() &&
5391-
FA->getFirstArg() == Attr->getFirstArg();
5392-
}))
5393-
MissingAttributes.push_back(FA);
5394-
}
5395-
5396-
continue;
5397-
}
5398-
5399-
ValueStmt *VS = dyn_cast_or_null<ValueStmt>(Child);
5400-
if (!VS)
5401-
continue;
5402-
Expr *TheExpr = VS->getExprStmt();
5403-
if (!TheExpr)
5404-
continue;
5405-
CallExpr *TheCall = dyn_cast_or_null<CallExpr>(TheExpr);
5406-
if (!TheCall)
5407-
continue;
5408-
const FunctionDecl *ChildFunction =
5409-
dyn_cast_or_null<FunctionDecl>(TheCall->getCalleeDecl());
5410-
if (!ChildFunction)
5411-
continue;
5412-
5413-
Expr **Args = TheCall->getArgs();
5414-
unsigned int NumArgs = TheCall->getNumArgs();
5415-
5416-
// If child expression is function, check if it is format function.
5417-
// If it is, check if parent function misses format attributes.
5418-
5419-
// If child function is format function and format arguments are not
5420-
// relevant to emit diagnostic, save only information about format type
5421-
// (format index and first-to-check argument index are set to -1).
5422-
// Information about format type is later used to determine if there are
5423-
// more than one format type found.
5424-
5425-
unsigned int ChildFunctionFormatArgumentIndexOffset =
5426-
checkIfMethodHasImplicitObjectParameter(ChildFunction) ? 2 : 1;
5427-
5428-
// Check if function has format attribute with forwarded format string.
5429-
IdentifierInfo *AttrType;
5430-
const ParmVarDecl *FormatArg;
5431-
if (!llvm::any_of(ChildFunction->specific_attrs<FormatAttr>(),
5432-
[&](const FormatAttr *Attr) {
5433-
AttrType = Attr->getType();
5434-
5435-
int OffsetFormatIndex =
5436-
Attr->getFormatIdx() -
5437-
ChildFunctionFormatArgumentIndexOffset;
5438-
if (OffsetFormatIndex < 0 ||
5439-
(unsigned)OffsetFormatIndex >= NumArgs)
5440-
return false;
5441-
5442-
const auto *FormatArgExpr = dyn_cast<DeclRefExpr>(
5443-
Args[OffsetFormatIndex]->IgnoreParenCasts());
5444-
if (!FormatArgExpr)
5445-
return false;
5446-
5447-
FormatArg = dyn_cast_or_null<ParmVarDecl>(
5448-
FormatArgExpr->getReferencedDeclOfCallee());
5449-
if (!FormatArg)
5450-
return false;
5451-
5452-
return true;
5453-
})) {
5454-
MissingAttributes.push_back(
5455-
FormatAttr::CreateImplicit(getASTContext(), AttrType, -1, -1));
5456-
continue;
5457-
}
5458-
5459-
// Do not add in a vector format attributes whose type is different than
5460-
// parent function attribute type.
5461-
if (llvm::any_of(FDecl->specific_attrs<FormatAttr>(),
5462-
[&](const FormatAttr *FunctionAttr) {
5463-
return AttrType != FunctionAttr->getType();
5464-
}))
5465-
continue;
5466-
5467-
// Check if format string argument is parent function parameter.
5468-
unsigned int StringIndex = 0;
5469-
if (!llvm::any_of(FDecl->parameters(), [&](const ParmVarDecl *Param) {
5470-
if (Param != FormatArg)
5471-
return false;
5472-
5473-
StringIndex = Param->getFunctionScopeIndex() +
5474-
FunctionFormatArgumentIndexOffset;
5475-
5476-
return true;
5477-
})) {
5478-
MissingAttributes.push_back(
5479-
FormatAttr::CreateImplicit(getASTContext(), AttrType, -1, -1));
5480-
continue;
5481-
}
5482-
5483-
unsigned NumOfParentFunctionParams = FDecl->getNumParams();
5484-
5485-
// Compare parent and calling function format attribute arguments (archetype
5486-
// and format string).
5487-
if (llvm::any_of(
5488-
FDecl->specific_attrs<FormatAttr>(), [&](const FormatAttr *Attr) {
5489-
if (Attr->getType() != AttrType)
5490-
return false;
5491-
int OffsetFormatIndex =
5492-
Attr->getFormatIdx() - FunctionFormatArgumentIndexOffset;
5493-
5494-
if (OffsetFormatIndex < 0 ||
5495-
(unsigned)OffsetFormatIndex >= NumOfParentFunctionParams)
5496-
return false;
5497-
5498-
if (FDecl->parameters()[OffsetFormatIndex] != FormatArg)
5499-
return false;
5500-
5501-
return true;
5502-
})) {
5503-
MissingAttributes.push_back(
5504-
FormatAttr::CreateImplicit(getASTContext(), AttrType, -1, -1));
5505-
continue;
5506-
}
5507-
5508-
// Get first argument index
5509-
unsigned FirstToCheck = [&]() -> unsigned {
5510-
if (!FDecl->isVariadic())
5511-
return 0;
5512-
const auto *FirstToCheckArg =
5513-
dyn_cast<DeclRefExpr>(Args[NumArgs - 1]->IgnoreParenCasts());
5514-
if (!FirstToCheckArg)
5515-
return 0;
5516-
5517-
if (FirstToCheckArg->getType().getCanonicalType() !=
5518-
Context.getBuiltinVaListType().getCanonicalType())
5519-
return 0;
5520-
return NumOfParentFunctionParams + FunctionFormatArgumentIndexOffset;
5521-
}();
5522-
5523-
// If there are already attributes which arguments matches arguments
5524-
// detected in this iteration, do not add new attribute as it would be
5525-
// duplicate.
5526-
if (!llvm::any_of(MissingAttributes, [&](const FormatAttr *Attr) {
5527-
return Attr->getType() == AttrType &&
5528-
Attr->getFormatIdx() == StringIndex &&
5529-
Attr->getFirstArg() == FirstToCheck;
5530-
}))
5531-
MissingAttributes.push_back(FormatAttr::CreateImplicit(
5532-
getASTContext(), AttrType, StringIndex, FirstToCheck));
5533-
}
5534-
5535-
return MissingAttributes;
5536-
}
5537-
55385323
//===----------------------------------------------------------------------===//
55395324
// Microsoft specific attribute handlers.
55405325
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)