@@ -1290,6 +1290,14 @@ static StringRef getEndOfLine() {
1290
1290
return EOL;
1291
1291
}
1292
1292
1293
+ // Returns the text indicating that the user needs to provide input there:
1294
+ std::string getUserFillPlaceHolder (StringRef HintTextToUser = " placeholder" ) {
1295
+ std::string s = std::string (" <# " );
1296
+ s += HintTextToUser;
1297
+ s += " #>" ;
1298
+ return s;
1299
+ }
1300
+
1293
1301
// Return the text representation of the given `APInt Val`:
1294
1302
static std::string getAPIntText (APInt Val) {
1295
1303
SmallVector<char > Txt;
@@ -1756,11 +1764,28 @@ static bool hasConflictingOverload(const FunctionDecl *FD) {
1756
1764
}
1757
1765
1758
1766
// Returns the text representation of clang::unsafe_buffer_usage attribute.
1759
- static std::string getUnsafeBufferUsageAttributeText () {
1760
- static const char *const RawAttr = " [[clang::unsafe_buffer_usage]]" ;
1761
- std::stringstream SS;
1762
- SS << RawAttr << getEndOfLine ().str ();
1763
- return SS.str ();
1767
+ // `WSSuffix` holds customized "white-space"s, e.g., newline or whilespace
1768
+ // characters.
1769
+ static std::string
1770
+ getUnsafeBufferUsageAttributeTextAt (SourceLocation Loc, Sema &S,
1771
+ StringRef WSSuffix = " " ) {
1772
+ Preprocessor &PP = S.getPreprocessor ();
1773
+ TokenValue ClangUnsafeBufferUsageTokens[] = {
1774
+ tok::l_square,
1775
+ tok::l_square,
1776
+ PP.getIdentifierInfo (" clang" ),
1777
+ tok::coloncolon,
1778
+ PP.getIdentifierInfo (" unsafe_buffer_usage" ),
1779
+ tok::r_square,
1780
+ tok::r_square};
1781
+
1782
+ StringRef MacroName;
1783
+
1784
+ // The returned macro (it returns) is guaranteed not to be function-like:
1785
+ MacroName = PP.getLastMacroWithSpelling (Loc, ClangUnsafeBufferUsageTokens);
1786
+ if (MacroName.empty ())
1787
+ MacroName = " [[clang::unsafe_buffer_usage]]" ;
1788
+ return MacroName.str () + WSSuffix.str ();
1764
1789
}
1765
1790
1766
1791
// For a `FunDecl`, one of whose `ParmVarDecl`s is being changed to have a new
@@ -1805,11 +1830,11 @@ static std::string getUnsafeBufferUsageAttributeText() {
1805
1830
static std::optional<FixItList>
1806
1831
createOverloadsForFixedParams (unsigned ParmIdx, StringRef NewTyText,
1807
1832
const FunctionDecl *FD, const ASTContext &Ctx,
1808
- UnsafeBufferUsageHandler &Handler) {
1833
+ UnsafeBufferUsageHandler &Handler, Sema &Sema ) {
1809
1834
// FIXME: need to make this conflict checking better:
1810
1835
if (hasConflictingOverload (FD))
1811
1836
return std::nullopt;
1812
-
1837
+
1813
1838
const SourceManager &SM = Ctx.getSourceManager ();
1814
1839
const LangOptions &LangOpts = Ctx.getLangOpts ();
1815
1840
// FIXME Respect indentation of the original code.
@@ -1859,7 +1884,7 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
1859
1884
// A lambda that creates the text representation of a function definition with
1860
1885
// the original signature:
1861
1886
const auto OldOverloadDefCreator =
1862
- [&Handler , &SM ,
1887
+ [&SM , &Sema ,
1863
1888
&LangOpts](const FunctionDecl *FD, unsigned ParmIdx,
1864
1889
StringRef NewTypeText) -> std::optional<std::string> {
1865
1890
std::stringstream SS;
@@ -1869,7 +1894,8 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
1869
1894
if (auto FDPrefix = getRangeText (
1870
1895
SourceRange (FD->getBeginLoc (), FD->getBody ()->getBeginLoc ()), SM,
1871
1896
LangOpts))
1872
- SS << getUnsafeBufferUsageAttributeText () << FDPrefix->str () << " {" ;
1897
+ SS << getUnsafeBufferUsageAttributeTextAt (FD->getBeginLoc (), Sema, " " )
1898
+ << FDPrefix->str () << " {" ;
1873
1899
else
1874
1900
return std::nullopt;
1875
1901
// Append: "return" func-name "("
@@ -1890,7 +1916,7 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
1890
1916
if (i == ParmIdx)
1891
1917
// This is our spanified paramter!
1892
1918
SS << NewTypeText.str () << " (" << Parm->getIdentifier ()->getName ().str () << " , "
1893
- << Handler. getUserFillPlaceHolder (" size" ) << " )" ;
1919
+ << getUserFillPlaceHolder (" size" ) << " )" ;
1894
1920
else
1895
1921
SS << Parm->getIdentifier ()->getName ().str ();
1896
1922
if (i != NumParms - 1 )
@@ -1921,7 +1947,8 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
1921
1947
// Adds the unsafe-buffer attribute (if not already there) to `FReDecl`:
1922
1948
if (!FReDecl->hasAttr <UnsafeBufferUsageAttr>()) {
1923
1949
FixIts.emplace_back (FixItHint::CreateInsertion (
1924
- FReDecl->getBeginLoc (), getUnsafeBufferUsageAttributeText ()));
1950
+ FReDecl->getBeginLoc (), getUnsafeBufferUsageAttributeTextAt (
1951
+ FReDecl->getBeginLoc (), Sema, " " )));
1925
1952
}
1926
1953
// Inserts a declaration with the new signature to the end of `FReDecl`:
1927
1954
if (auto NewOverloadDecl =
@@ -1938,7 +1965,7 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
1938
1965
// new overload of the function so that the change is self-contained (see
1939
1966
// `createOverloadsForFixedParams`).
1940
1967
static FixItList fixParamWithSpan (const ParmVarDecl *PVD, const ASTContext &Ctx,
1941
- UnsafeBufferUsageHandler &Handler) {
1968
+ UnsafeBufferUsageHandler &Handler, Sema &Sema ) {
1942
1969
if (PVD->hasDefaultArg ())
1943
1970
// FIXME: generate fix-its for default values:
1944
1971
return {};
@@ -1990,7 +2017,7 @@ static FixItList fixParamWithSpan(const ParmVarDecl *PVD, const ASTContext &Ctx,
1990
2017
}
1991
2018
if (ParmIdx < FD->getNumParams ())
1992
2019
if (auto OverloadFix = createOverloadsForFixedParams (ParmIdx, SpanTyText,
1993
- FD, Ctx, Handler)) {
2020
+ FD, Ctx, Handler, Sema )) {
1994
2021
Fixes.append (*OverloadFix);
1995
2022
return Fixes;
1996
2023
}
@@ -2013,7 +2040,7 @@ static FixItList fixVariableWithSpan(const VarDecl *VD,
2013
2040
(void )DS;
2014
2041
2015
2042
// FIXME: handle cases where DS has multiple declarations
2016
- return fixVarDeclWithSpan (VD, Ctx, Handler. getUserFillPlaceHolder ());
2043
+ return fixVarDeclWithSpan (VD, Ctx, getUserFillPlaceHolder ());
2017
2044
}
2018
2045
2019
2046
// TODO: we should be consistent to use `std::nullopt` to represent no-fix due
@@ -2022,7 +2049,7 @@ static FixItList
2022
2049
fixVariable (const VarDecl *VD, Strategy::Kind K,
2023
2050
/* The function decl under analysis */ const Decl *D,
2024
2051
const DeclUseTracker &Tracker, ASTContext &Ctx,
2025
- UnsafeBufferUsageHandler &Handler) {
2052
+ UnsafeBufferUsageHandler &Handler, Sema &Sema ) {
2026
2053
if (const auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
2027
2054
auto *FD = dyn_cast<clang::FunctionDecl>(PVD->getDeclContext ());
2028
2055
if (!FD || FD != D)
@@ -2049,7 +2076,7 @@ fixVariable(const VarDecl *VD, Strategy::Kind K,
2049
2076
case Strategy::Kind::Span: {
2050
2077
if (VD->getType ()->isPointerType ()) {
2051
2078
if (const auto *PVD = dyn_cast<ParmVarDecl>(VD))
2052
- return fixParamWithSpan (PVD, Ctx, Handler);
2079
+ return fixParamWithSpan (PVD, Ctx, Handler, Sema );
2053
2080
2054
2081
if (VD->isLocalVarDecl ())
2055
2082
return fixVariableWithSpan (VD, Tracker, Ctx, Handler);
@@ -2097,11 +2124,11 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
2097
2124
ASTContext &Ctx,
2098
2125
/* The function decl under analysis */ const Decl *D,
2099
2126
const DeclUseTracker &Tracker, UnsafeBufferUsageHandler &Handler,
2100
- const DefMapTy &VarGrpMap) {
2127
+ const DefMapTy &VarGrpMap, Sema &Sema ) {
2101
2128
std::map<const VarDecl *, FixItList> FixItsForVariable;
2102
2129
for (const auto &[VD, Fixables] : FixablesForAllVars.byVar ) {
2103
2130
FixItsForVariable[VD] =
2104
- fixVariable (VD, S.lookup (VD), D, Tracker, Ctx, Handler);
2131
+ fixVariable (VD, S.lookup (VD), D, Tracker, Ctx, Handler, Sema );
2105
2132
// If we fail to produce Fix-It for the declaration we have to skip the
2106
2133
// variable entirely.
2107
2134
if (FixItsForVariable[VD].empty ()) {
@@ -2171,7 +2198,7 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
2171
2198
FixItList GroupFix;
2172
2199
if (FixItsForVariable.find (Var) == FixItsForVariable.end ()) {
2173
2200
GroupFix = fixVariable (Var, ReplacementTypeForVD, D,
2174
- Tracker, Var->getASTContext (), Handler);
2201
+ Tracker, Var->getASTContext (), Handler, Sema );
2175
2202
} else {
2176
2203
GroupFix = FixItsForVariable[Var];
2177
2204
}
@@ -2197,7 +2224,7 @@ getNaiveStrategy(const llvm::SmallVectorImpl<const VarDecl *> &UnsafeVars) {
2197
2224
2198
2225
void clang::checkUnsafeBufferUsage (const Decl *D,
2199
2226
UnsafeBufferUsageHandler &Handler,
2200
- bool EmitSuggestions) {
2227
+ bool EmitSuggestions, Sema &Sema ) {
2201
2228
assert (D && D->getBody ());
2202
2229
2203
2230
// Do not emit fixit suggestions for functions declared in an
@@ -2343,7 +2370,7 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
2343
2370
2344
2371
FixItsForVariableGroup =
2345
2372
getFixIts (FixablesForAllVars, NaiveStrategy, D->getASTContext (), D,
2346
- Tracker, Handler, VariableGroupsMap);
2373
+ Tracker, Handler, VariableGroupsMap, Sema );
2347
2374
2348
2375
// FIXME Detect overlapping FixIts.
2349
2376
0 commit comments