diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -6511,29 +6511,42 @@ CurrTL = ATL.getValueLoc().getUnqualifiedLoc(); } - while (MacroQualifiedTypeLoc TL = CurrTL.getAs()) { - TL.setExpansionLoc( - State.getExpansionLocForMacroQualifiedType(TL.getTypePtr())); - CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); - } + bool HasDesugaredTypeLoc = true; + while (HasDesugaredTypeLoc) { + switch (CurrTL.getTypeLocClass()) { + case TypeLoc::MacroQualified: { + auto TL = CurrTL.castAs(); + TL.setExpansionLoc( + State.getExpansionLocForMacroQualifiedType(TL.getTypePtr())); + CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + break; + } - while (AttributedTypeLoc TL = CurrTL.getAs()) { - fillAttributedTypeLoc(TL, State); - CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); - } + case TypeLoc::Attributed: { + auto TL = CurrTL.castAs(); + fillAttributedTypeLoc(TL, State); + CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + break; + } - while (BTFTagAttributedTypeLoc TL = CurrTL.getAs()) - CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + case TypeLoc::Adjusted: + case TypeLoc::BTFTagAttributed: { + CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); + break; + } - while (DependentAddressSpaceTypeLoc TL = - CurrTL.getAs()) { - fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs()); - CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc(); - } + case TypeLoc::DependentAddressSpace: { + auto TL = CurrTL.castAs(); + fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs()); + CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc(); + break; + } - // FIXME: Ordering here? - while (AdjustedTypeLoc TL = CurrTL.getAs()) - CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + default: + HasDesugaredTypeLoc = false; + break; + } + } DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); diff --git a/clang/unittests/AST/SourceLocationTest.cpp b/clang/unittests/AST/SourceLocationTest.cpp --- a/clang/unittests/AST/SourceLocationTest.cpp +++ b/clang/unittests/AST/SourceLocationTest.cpp @@ -438,6 +438,47 @@ loc(unaryTransformType()))); } +TEST(PointerTypeLoc, StarLoc) { + llvm::Annotations Example(R"c( + int $star^*var; + )c"); + + auto AST = tooling::buildASTFromCode(Example.code()); + SourceManager &SM = AST->getSourceManager(); + auto &Ctx = AST->getASTContext(); + + auto *VD = selectFirst("vd", match(varDecl(hasName("var")).bind("vd"), Ctx)); + ASSERT_NE(VD, nullptr); + + auto TL = + VD->getTypeSourceInfo()->getTypeLoc().castAs(); + ASSERT_EQ(SM.getFileOffset(TL.getStarLoc()), Example.point("star")); +} + +TEST(PointerTypeLoc, StarLocBehindSugar) { + llvm::Annotations Example(R"c( + #define NODEREF __attribute__((noderef)) + char $1st^* NODEREF _Nonnull $2nd^* var; + )c"); + + auto AST = tooling::buildASTFromCode(Example.code()); + SourceManager &SM = AST->getSourceManager(); + auto &Ctx = AST->getASTContext(); + + auto *VD = selectFirst("vd", match(varDecl(hasName("var")).bind("vd"), Ctx)); + ASSERT_NE(VD, nullptr); + + auto TL = VD->getTypeSourceInfo()->getTypeLoc().castAs(); + EXPECT_EQ(SM.getFileOffset(TL.getStarLoc()), Example.point("2nd")); + + // Cast intermediate TypeLoc to make sure the structure matches expectations. + auto InnerPtrTL = TL.getPointeeLoc().castAs() + .getNextTypeLoc().castAs() + .getNextTypeLoc().castAs() + .getNextTypeLoc().castAs(); + EXPECT_EQ(SM.getFileOffset(InnerPtrTL.getStarLoc()), Example.point("1st")); +} + TEST(CXXFunctionalCastExpr, SourceRange) { RangeVerifier Verifier; Verifier.expectRange(2, 10, 2, 14);