8
8
9
9
#include " UseAutoCheck.h"
10
10
#include " clang/AST/ASTContext.h"
11
+ #include " clang/AST/TypeLoc.h"
11
12
#include " clang/ASTMatchers/ASTMatchFinder.h"
12
13
#include " clang/ASTMatchers/ASTMatchers.h"
13
14
#include " clang/Basic/CharInfo.h"
14
15
#include " clang/Tooling/FixIt.h"
16
+ #include " llvm/ADT/STLExtras.h"
15
17
16
18
using namespace clang ;
17
19
using namespace clang ::ast_matchers;
@@ -333,6 +335,25 @@ void UseAutoCheck::replaceIterators(const DeclStmt *D, ASTContext *Context) {
333
335
<< FixItHint::CreateReplacement (Range, " auto" );
334
336
}
335
337
338
+ static void ignoreTypeLocClasses (
339
+ TypeLoc &Loc,
340
+ std::initializer_list<TypeLoc::TypeLocClass> const &LocClasses) {
341
+ while (llvm::is_contained (LocClasses, Loc.getTypeLocClass ()))
342
+ Loc = Loc.getNextTypeLoc ();
343
+ }
344
+
345
+ static bool isMutliLevelPointerToTypeLocClasses (
346
+ TypeLoc Loc,
347
+ std::initializer_list<TypeLoc::TypeLocClass> const &LocClasses) {
348
+ ignoreTypeLocClasses (Loc, {TypeLoc::Paren, TypeLoc::Qualified});
349
+ TypeLoc::TypeLocClass TLC = Loc.getTypeLocClass ();
350
+ if (TLC != TypeLoc::Pointer && TLC != TypeLoc::MemberPointer)
351
+ return false ;
352
+ ignoreTypeLocClasses (Loc, {TypeLoc::Paren, TypeLoc::Qualified,
353
+ TypeLoc::Pointer, TypeLoc::MemberPointer});
354
+ return llvm::is_contained (LocClasses, Loc.getTypeLocClass ());
355
+ }
356
+
336
357
void UseAutoCheck::replaceExpr (
337
358
const DeclStmt *D, ASTContext *Context,
338
359
llvm::function_ref<QualType(const Expr *)> GetType, StringRef Message) {
@@ -342,6 +363,10 @@ void UseAutoCheck::replaceExpr(
342
363
return ;
343
364
344
365
const QualType FirstDeclType = FirstDecl->getType ().getCanonicalType ();
366
+ TypeSourceInfo *TSI = FirstDecl->getTypeSourceInfo ();
367
+
368
+ if (TSI == nullptr )
369
+ return ;
345
370
346
371
std::vector<FixItHint> StarRemovals;
347
372
for (const auto *Dec : D->decls ()) {
@@ -383,17 +408,11 @@ void UseAutoCheck::replaceExpr(
383
408
// is the same as the initializer, just more CV-qualified. However, TypeLoc
384
409
// information is not reliable where CV qualifiers are concerned so we can't
385
410
// do anything about this case for now.
386
- TypeLoc Loc = FirstDecl->getTypeSourceInfo ()->getTypeLoc ();
387
- if (!RemoveStars) {
388
- while (Loc.getTypeLocClass () == TypeLoc::Pointer ||
389
- Loc.getTypeLocClass () == TypeLoc::Qualified)
390
- Loc = Loc.getNextTypeLoc ();
391
- }
392
- while (Loc.getTypeLocClass () == TypeLoc::LValueReference ||
393
- Loc.getTypeLocClass () == TypeLoc::RValueReference ||
394
- Loc.getTypeLocClass () == TypeLoc::Qualified) {
395
- Loc = Loc.getNextTypeLoc ();
396
- }
411
+ TypeLoc Loc = TSI->getTypeLoc ();
412
+ if (!RemoveStars)
413
+ ignoreTypeLocClasses (Loc, {TypeLoc::Pointer, TypeLoc::Qualified});
414
+ ignoreTypeLocClasses (Loc, {TypeLoc::LValueReference, TypeLoc::RValueReference,
415
+ TypeLoc::Qualified});
397
416
SourceRange Range (Loc.getSourceRange ());
398
417
399
418
if (MinTypeNameLength != 0 &&
@@ -405,12 +424,19 @@ void UseAutoCheck::replaceExpr(
405
424
406
425
auto Diag = diag (Range.getBegin (), Message);
407
426
427
+ bool ShouldReplenishVariableName = isMutliLevelPointerToTypeLocClasses (
428
+ TSI->getTypeLoc (), {TypeLoc::FunctionProto, TypeLoc::ConstantArray});
429
+
408
430
// Space after 'auto' to handle cases where the '*' in the pointer type is
409
431
// next to the identifier. This avoids changing 'int *p' into 'autop'.
410
- // FIXME: This doesn't work for function pointers because the variable name
411
- // is inside the type.
412
- Diag << FixItHint::CreateReplacement (Range, RemoveStars ? " auto " : " auto" )
413
- << StarRemovals;
432
+ llvm::StringRef Auto = ShouldReplenishVariableName
433
+ ? (RemoveStars ? " auto " : " auto *" )
434
+ : (RemoveStars ? " auto " : " auto" );
435
+ std::string ReplenishedVariableName =
436
+ ShouldReplenishVariableName ? FirstDecl->getQualifiedNameAsString () : " " ;
437
+ std::string Replacement =
438
+ (Auto + llvm::StringRef{ReplenishedVariableName}).str ();
439
+ Diag << FixItHint::CreateReplacement (Range, Replacement) << StarRemovals;
414
440
}
415
441
416
442
void UseAutoCheck::check (const MatchFinder::MatchResult &Result) {
0 commit comments