Commit ce79c424 authored by Marcel Hlopko's avatar Marcel Hlopko Committed by Dmitri Gribenko
Browse files

[Sema] Fix location of star ('*') inside MemberPointerTypeLoc

Summary: Copy of https://reviews.llvm.org/D72073?id=235842, submitting with ilya-biryukov's permission.

Reviewers: gribozavr, gribozavr2

Reviewed By: gribozavr2

Subscribers: mgorny, gribozavr2, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D76061
parent db1f40d1
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -1518,6 +1518,8 @@ struct DeclaratorChunk {
  struct MemberPointerTypeInfo {
    /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic.
    unsigned TypeQuals : 5;
    /// Location of the '*' token.
    unsigned StarLoc;
    // CXXScopeSpec has a constructor, so it can't be a direct member.
    // So we need some pointer-aligned storage and a bit of trickery.
    alignas(CXXScopeSpec) char ScopeMem[sizeof(CXXScopeSpec)];
@@ -1660,11 +1662,13 @@ struct DeclaratorChunk {

  static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
                                          unsigned TypeQuals,
                                          SourceLocation Loc) {
                                          SourceLocation StarLoc,
                                          SourceLocation EndLoc) {
    DeclaratorChunk I;
    I.Kind          = MemberPointer;
    I.Loc           = SS.getBeginLoc();
    I.EndLoc        = Loc;
    I.EndLoc = EndLoc;
    I.Mem.StarLoc = StarLoc.getRawEncoding();
    I.Mem.TypeQuals = TypeQuals;
    new (I.Mem.ScopeMem) CXXScopeSpec(SS);
    return I;
+3 −3
Original line number Diff line number Diff line
@@ -5643,8 +5643,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
        return;
      }

      SourceLocation Loc = ConsumeToken();
      D.SetRangeEnd(Loc);
      SourceLocation StarLoc = ConsumeToken();
      D.SetRangeEnd(StarLoc);
      DeclSpec DS(AttrFactory);
      ParseTypeQualifierListOpt(DS);
      D.ExtendWithDeclSpec(DS);
@@ -5655,7 +5655,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
      // Sema will have to catch (syntactically invalid) pointers into global
      // scope. It has to catch pointers into namespace scope anyway.
      D.AddTypeInfo(DeclaratorChunk::getMemberPointer(
                        SS, DS.getTypeQualifiers(), DS.getEndLoc()),
                        SS, DS.getTypeQualifiers(), StarLoc, DS.getEndLoc()),
                    std::move(DS.getAttributes()),
                    /* Don't replace range end. */ SourceLocation());
      return;
+1 −1
Original line number Diff line number Diff line
@@ -5840,7 +5840,7 @@ namespace {
      }

      // Finally fill in MemberPointerLocInfo fields.
      TL.setStarLoc(Chunk.Loc);
      TL.setStarLoc(SourceLocation::getFromRawEncoding(Chunk.Mem.StarLoc));
      TL.setClassTInfo(ClsTInfo);
    }
    void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+1 −0
Original line number Diff line number Diff line
@@ -42,4 +42,5 @@ clang_target_link_libraries(ASTTests
  clangFrontend
  clangSerialization
  clangTooling
  LLVMTestingSupport
  )
+20 −1
Original line number Diff line number Diff line
@@ -15,11 +15,12 @@
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTContext.h"
#include "MatchVerifier.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Testing/Support/Annotations.h"
#include "gtest/gtest.h"

namespace clang {
@@ -842,5 +843,23 @@ TEST(FunctionDecl, ExceptionSpecifications) {
                              Language::Lang_CXX11));
}

TEST(Decl, MemberPointerStarLoc) {
  llvm::Annotations Example(R"cpp(
    struct X {};
    int X::$star^* a;
  )cpp");

  auto AST = tooling::buildASTFromCode(Example.code());
  SourceManager &SM = AST->getSourceManager();
  auto &Ctx = AST->getASTContext();

  auto *VD = selectFirst<VarDecl>("vd", match(varDecl().bind("vd"), Ctx));
  ASSERT_TRUE(VD != nullptr);

  auto TL =
      VD->getTypeSourceInfo()->getTypeLoc().castAs<MemberPointerTypeLoc>();
  ASSERT_EQ(SM.getFileOffset(TL.getStarLoc()), Example.point("star"));
}

} // end namespace ast_matchers
} // end namespace clang