leonardchan updated this revision to Diff 184439. leonardchan marked 15 inline comments as done.
Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D51329/new/ https://reviews.llvm.org/D51329 Files: clang/include/clang/AST/ASTContext.h clang/include/clang/AST/RecursiveASTVisitor.h clang/include/clang/AST/Type.h clang/include/clang/AST/TypeLoc.h clang/include/clang/AST/TypeNodes.def clang/include/clang/Parse/Parser.h clang/include/clang/Sema/ParsedAttr.h clang/include/clang/Sema/Sema.h clang/include/clang/Serialization/ASTBitCodes.h clang/lib/ARCMigrate/TransGCAttrs.cpp clang/lib/AST/ASTContext.cpp clang/lib/AST/ASTDiagnostic.cpp clang/lib/AST/ASTStructuralEquivalence.cpp clang/lib/AST/ItaniumMangle.cpp clang/lib/AST/Type.cpp clang/lib/AST/TypePrinter.cpp clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CodeGenFunction.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaStmt.cpp clang/lib/Sema/SemaType.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/Frontend/macro_defined_type.cpp clang/test/Sema/address_space_print_macro.c clang/test/Sema/address_spaces.c clang/test/SemaObjC/externally-retained.m clang/test/SemaObjC/gc-attributes.m clang/test/SemaObjC/mrc-weak.m clang/test/SemaObjCXX/gc-attributes.mm clang/tools/libclang/CIndex.cpp
Index: clang/tools/libclang/CIndex.cpp =================================================================== --- clang/tools/libclang/CIndex.cpp +++ clang/tools/libclang/CIndex.cpp @@ -1615,6 +1615,10 @@ return Visit(TL.getInnerLoc()); } +bool CursorVisitor::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) { + return Visit(TL.getInnerLoc()); +} + bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) { return Visit(TL.getPointeeLoc()); } Index: clang/test/SemaObjCXX/gc-attributes.mm =================================================================== --- clang/test/SemaObjCXX/gc-attributes.mm +++ clang/test/SemaObjCXX/gc-attributes.mm @@ -3,7 +3,7 @@ @interface A @end -void f0(__strong A**); // expected-note{{candidate function not viable: 1st argument ('A *__weak *') has __weak ownership, but parameter has __strong ownership}} +void f0(__strong A **); // expected-note{{candidate function not viable: 1st argument ('__weak A **') has __weak ownership, but parameter has __strong ownership}} void test_f0() { A *a; @@ -12,7 +12,7 @@ f0(&a2); // expected-error{{no matching function}} } -void f1(__weak A**); // expected-note{{candidate function not viable: 1st argument ('A *__strong *') has __strong ownership, but parameter has __weak ownership}} +void f1(__weak A **); // expected-note{{candidate function not viable: 1st argument ('__strong A **') has __strong ownership, but parameter has __weak ownership}} void test_f1() { A *a; Index: clang/test/SemaObjC/mrc-weak.m =================================================================== --- clang/test/SemaObjC/mrc-weak.m +++ clang/test/SemaObjC/mrc-weak.m @@ -62,6 +62,6 @@ void test_cast_qualifier_inference(__weak id *value) { __weak id *a = (id*) value; - __unsafe_unretained id *b = (id*) value; // expected-error {{initializing 'id *' with an expression of type '__weak id *' changes retain/release properties of pointer}} + __unsafe_unretained id *b = (id *)value; // expected-error {{initializing '__unsafe_unretained id *' with an expression of type '__weak id *' changes retain/release properties of pointer}} } Index: clang/test/SemaObjC/gc-attributes.m =================================================================== --- clang/test/SemaObjC/gc-attributes.m +++ clang/test/SemaObjC/gc-attributes.m @@ -9,7 +9,7 @@ A *a; static __weak A *a2; f0(&a); - f0(&a2); // expected-warning{{passing 'A *__weak *' to parameter of type 'A *__strong *' discards qualifiers}} + f0(&a2); // expected-warning{{passing '__weak A **' to parameter of type '__strong A **' discards qualifiers}} } void f1(__weak A**); // expected-note{{passing argument to parameter here}} @@ -18,7 +18,7 @@ A *a; __strong A *a2; f1(&a); - f1(&a2); // expected-warning{{passing 'A *__strong *' to parameter of type 'A *__weak *' discards qualifiers}} + f1(&a2); // expected-warning{{passing '__strong A **' to parameter of type '__weak A **' discards qualifiers}} } // These qualifiers should silently expand to nothing in GC mode. Index: clang/test/SemaObjC/externally-retained.m =================================================================== --- clang/test/SemaObjC/externally-retained.m +++ clang/test/SemaObjC/externally-retained.m @@ -68,6 +68,12 @@ second = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} }; +void (^blk2)(ObjCTy *, ObjCTy *) = + ^(__strong ObjCTy *first, ObjCTy *second) __attribute__((objc_externally_retained)) { + first = 0; + second = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}} +}; + void test8(EXT_RET ObjCTy *x) {} // expected-warning{{'objc_externally_retained' attribute only applies to variables}} #pragma clang attribute ext_ret.push(__attribute__((objc_externally_retained)), apply_to=any(function, block, objc_method)) Index: clang/test/Sema/address_spaces.c =================================================================== --- clang/test/Sema/address_spaces.c +++ clang/test/Sema/address_spaces.c @@ -71,7 +71,7 @@ // Clang extension doesn't forbid operations on pointers to different address spaces. char* cmp(_AS1 char *x, _AS2 char *y) { - return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *') which are pointers to non-overlapping address spaces}} + return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type ('_AS1 char *' and '_AS2 char *') which are pointers to non-overlapping address spaces}} } struct SomeStruct { Index: clang/test/Sema/address_space_print_macro.c =================================================================== --- /dev/null +++ clang/test/Sema/address_space_print_macro.c @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify + +#define AS1 __attribute__((address_space(1))) +#define AS2 __attribute__((address_space(2), annotate("foo"))) +#define AS_ND __attribute__((address_space(2), noderef)) + +#define AS(i) address_space(i) +#define AS3 __attribute__((AS(3))) + +#define ATTR __attribute__ +#define AS4 ATTR((AS(4))) +#define AS5 __attribute__((address_space(5))) char + +char *cmp(AS1 char *x, AS2 char *y) { + return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type ('AS1 char *' and 'AS2 char *') which are pointers to non-overlapping address spaces}} +} + +__attribute__((address_space(1))) char test_array[10]; +void test3(void) { + extern void test3_helper(char *p); // expected-note{{passing argument to parameter 'p' here}} + test3_helper(test_array); // expected-error{{passing '__attribute__((address_space(1))) char *' to parameter of type 'char *' changes address space of pointer}} +} + +char AS2 *test4_array; +void test4(void) { + extern void test3_helper(char *p); // expected-note{{passing argument to parameter 'p' here}} + test3_helper(test4_array); // expected-error{{passing 'AS2 char *' to parameter of type 'char *' changes address space of pointer}} +} + +void func() { + char AS1 *x; + char AS3 *x2; + AS4 char *x3; + AS5 *x4; + char *y; + y = x; // expected-error{{assigning 'AS1 char *' to 'char *' changes address space of pointer}} + y = x2; // expected-error{{assigning 'AS3 char *' to 'char *' changes address space of pointer}} + y = x3; // expected-error{{assigning 'AS4 char *' to 'char *' changes address space of pointer}} + y = x4; // expected-error{{assigning '__attribute__((address_space(5))) char *' to 'char *' changes address space of pointer}} +} + +void multiple_attrs(AS_ND int *x) { + __attribute__((address_space(2))) int *y = x; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} +} + +void override_macro_name() { +#define ATTRS __attribute__((noderef)) // expected-note{{previous definition is here}} + ATTRS +#define ATTRS __attribute__((address_space(1))) // expected-warning{{'ATTRS' macro redefined}} + ATTRS + int *x; + + int AS_ND *y = x; // expected-error{{initializing 'AS_ND int *' with an expression of type 'ATTRS int *' changes address space of pointer}} +} + +void partial_macro_declaration() { +#define ATTRS2 __attribute__((noderef)) + ATTRS2 __attribute__((address_space(1))) int *x; + + int AS_ND *y = x; // expected-error{{initializing 'AS_ND int *' with an expression of type 'ATTRS2 int __attribute__((address_space(1))) *' changes address space of pointer}} + + // The attribute not wrapped with a macro should be printed regularly. +#define ATTRS3 __attribute__((address_space(1))) + ATTRS3 __attribute__((noderef)) int *x2; + + int AS_ND *y2 = x2; // expected-error{{initializing 'AS_ND int *' with an expression of type 'ATTRS3 int * __attribute__((noderef))' changes address space of pointer}} +} Index: clang/test/Frontend/macro_defined_type.cpp =================================================================== --- /dev/null +++ clang/test/Frontend/macro_defined_type.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#define NODEREF __attribute__((noderef)) + +void Func() { + int NODEREF i; // expected-warning{{'noderef' can only be used on an array or pointer type}} + int NODEREF *i_ptr; + + // There should be no difference whether a macro defined type is used or not. + auto __attribute__((noderef)) *auto_i_ptr = i_ptr; + auto __attribute__((noderef)) auto_i = i; // expected-warning{{'noderef' can only be used on an array or pointer type}} + + auto NODEREF *auto_i_ptr2 = i_ptr; + auto NODEREF auto_i2 = i; // expected-warning{{'noderef' can only be used on an array or pointer type}} +} Index: clang/lib/Serialization/ASTWriter.cpp =================================================================== --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -516,6 +516,13 @@ Code = TYPE_PAREN; } +void ASTTypeWriter::VisitMacroQualifiedType(const MacroQualifiedType *T) { + Record.AddTypeRef(T->getUnderlyingType()); + Record.AddIdentifierRef(T->getMacroIdentifier()); + Record.AddSourceLocation(T->getExpansionLoc()); + Code = TYPE_MACRO_DEFINED; +} + void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) { Record.push_back(T->getKeyword()); Record.AddNestedNameSpecifier(T->getQualifier()); @@ -802,6 +809,8 @@ Record.AddSourceLocation(TL.getRParenLoc()); } +void TypeLocWriter::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {} + void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { Record.AddSourceLocation(TL.getElaboratedKeywordLoc()); Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); @@ -1219,6 +1228,7 @@ RECORD(TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION); RECORD(TYPE_DEPENDENT_SIZED_ARRAY); RECORD(TYPE_PAREN); + RECORD(TYPE_MACRO_DEFINED); RECORD(TYPE_PACK_EXPANSION); RECORD(TYPE_ATTRIBUTED); RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK); Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -6178,6 +6178,17 @@ return Context.getParenType(InnerType); } + case TYPE_MACRO_DEFINED: { + if (Record.size() != 3) { + Error("incorrect encoding of macro defined type"); + return QualType(); + } + QualType UnderlyingTy = readType(*Loc.F, Record, Idx); + IdentifierInfo *MacroII = GetIdentifierInfo(*Loc.F, Record, Idx); + SourceLocation ExpansionLoc = ReadSourceLocation(*Loc.F, Record[2]); + return Context.getMacroQualifiedType(UnderlyingTy, MacroII, ExpansionLoc); + } + case TYPE_PACK_EXPANSION: { if (Record.size() != 2) { Error("incorrect encoding of pack expansion type"); @@ -6499,6 +6510,8 @@ // nothing to do } +void TypeLocReader::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {} + void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { TL.setCaretLoc(ReadSourceLocation()); } Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -873,6 +873,12 @@ return SemaRef.Context.getTypeDeclType(Typedef); } + /// Build a new MacroDefined type. + QualType RebuildMacroQualifiedType(QualType T, const IdentifierInfo *MacroII, + SourceLocation ExpansionLoc) { + return SemaRef.Context.getMacroQualifiedType(T, MacroII, ExpansionLoc); + } + /// Build a new class/struct/union type. QualType RebuildRecordType(RecordDecl *Record) { return SemaRef.Context.getTypeDeclType(Record); @@ -6159,6 +6165,26 @@ return Result; } +template <typename Derived> +QualType +TreeTransform<Derived>::TransformMacroQualifiedType(TypeLocBuilder &TLB, + MacroQualifiedTypeLoc TL) { + QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc()); + if (Inner.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || Inner != TL.getInnerLoc().getType()) { + Result = getDerived().RebuildMacroQualifiedType( + Inner, TL.getMacroIdentifier(), TL.getExpansionLoc()); + if (Result.isNull()) + return QualType(); + } + + TLB.push<MacroQualifiedTypeLoc>(Result); + return Result; +} + template<typename Derived> QualType TreeTransform<Derived>::TransformDependentNameType( TypeLocBuilder &TLB, DependentNameTypeLoc TL) { Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -33,6 +33,7 @@ #include "clang/Sema/TemplateInstCallback.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" @@ -5618,6 +5619,7 @@ assert(Chunk.Kind == DeclaratorChunk::Pipe); TL.setKWLoc(Chunk.Loc); } + void VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {} void VisitTypeLoc(TypeLoc TL) { llvm_unreachable("unsupported TypeLoc kind in declarator!"); @@ -5696,6 +5698,9 @@ CurrTL = ATL.getValueLoc().getUnqualifiedLoc(); } + while (MacroQualifiedTypeLoc TL = CurrTL.getAs<MacroQualifiedTypeLoc>()) + CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) { fillAttributedTypeLoc(TL, State); CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); @@ -6958,12 +6963,12 @@ return true; } -bool Sema::hasExplicitCallingConv(QualType &T) { - QualType R = T.IgnoreParens(); - while (const AttributedType *AT = dyn_cast<AttributedType>(R)) { +bool Sema::hasExplicitCallingConv(QualType T) { + const AttributedType *AT; + while ((AT = T->getAs<AttributedType>()) && !isa<TypedefType>(T)) { if (AT->isCallingConv()) return true; - R = AT->getModifiedType().IgnoreParens(); + T = AT->getModifiedType(); } return false; } @@ -7365,6 +7370,7 @@ // over that. ParsedAttributesView AttrsCopy{attrs}; + llvm::StringMap<llvm::SmallVector<const IdentifierInfo *, 2>> FoundMacros; state.setParsedNoDeref(false); for (ParsedAttr &attr : AttrsCopy) { @@ -7543,6 +7549,14 @@ distributeFunctionTypeAttr(state, attr, type); break; } + + // Handle attributes that are defined in a macro. + if (isa<AttributedType>(type) && attr.hasMacroIdentifier() && + !type.getQualifiers().hasObjCLifetime()) { + const IdentifierInfo *MacroII = attr.getMacroIdentifier(); + type = state.getSema().Context.getMacroQualifiedType( + type, MacroII, attr.getMacroExpansionLoc()); + } } if (!state.getSema().getLangOpts().OpenCL || Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -3386,10 +3386,10 @@ } TypeLoc Sema::getReturnTypeLoc(FunctionDecl *FD) const { - TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); - while (auto ATL = TL.getAs<AttributedTypeLoc>()) - TL = ATL.getModifiedLoc().IgnoreParens(); - return TL.castAs<FunctionProtoTypeLoc>().getReturnLoc(); + return FD->getTypeSourceInfo() + ->getTypeLoc() + .getAsAdjusted<FunctionProtoTypeLoc>() + .getReturnLoc(); } /// Deduce the return type for a function from a returned expression, per Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -4102,6 +4102,7 @@ case Type::Attributed: case Type::SubstTemplateTypeParm: case Type::PackExpansion: + case Type::MacroQualified: // Keep walking after single level desugaring. T = T.getSingleStepDesugaredType(Context); break; @@ -13661,8 +13662,8 @@ // Look for an explicit signature in that function type. FunctionProtoTypeLoc ExplicitSignature; - if ((ExplicitSignature = - Sig->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>())) { + if ((ExplicitSignature = Sig->getTypeLoc() + .getAsAdjusted<FunctionProtoTypeLoc>())) { // Check whether that explicit signature was synthesized by // GetTypeForDeclarator. If so, don't save that as part of the Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -85,6 +85,61 @@ #undef CLANG_ATTR_LATE_PARSED_LIST } +/// Attempt to find the outermost macro expansions that contains a given start +/// and end source location that share the same FileID. +static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc, + SourceLocation EndLoc, + SourceLocation &FoundStartLocExpansion, + SourceLocation &FoundEndLocExpansion) { + llvm::SmallVector<SourceLocation, 8> StartLocs; + SourceManager &SM = PP.getSourceManager(); + + // Generate starting locations FileIDs + while (StartLoc.isMacroID()) { + FileID FID = SM.getFileID(StartLoc); + const SrcMgr::SLocEntry *E = &SM.getSLocEntry(FID); + const SrcMgr::ExpansionInfo &Expansion = E->getExpansion(); + if (!Expansion.isFunctionMacroExpansion()) + StartLocs.push_back(StartLoc); + StartLoc = Expansion.getExpansionLocStart(); + } + + // Generate end location FileIDs + llvm::DenseMap<FileID, SourceLocation> EndLocs; + while (EndLoc.isMacroID()) { + FileID FID = SM.getFileID(EndLoc); + const SrcMgr::SLocEntry *E = &SM.getSLocEntry(FID); + const SrcMgr::ExpansionInfo &Expansion = E->getExpansion(); + if (!Expansion.isFunctionMacroExpansion()) + EndLocs[FID] = EndLoc; + EndLoc = Expansion.getExpansionLocStart(); + } + + // Find last common FileID. This will just be the last found starting FileID + // found from the starting loc expansion. + for (auto I = StartLocs.rbegin(); I != StartLocs.rend(); ++I) { + FileID FID = SM.getFileID(*I); + auto FoundEndLoc = EndLocs.find(FID); + if (FoundEndLoc != EndLocs.end()) { + FoundStartLocExpansion = *I; + FoundEndLocExpansion = FoundEndLoc->second; + + bool AttrStartIsInMacro = + (FoundStartLocExpansion.isMacroID() && + Lexer::isAtStartOfMacroExpansion(FoundStartLocExpansion, SM, + PP.getLangOpts())); + bool AttrEndIsInMacro = (FoundEndLocExpansion.isMacroID() && + Lexer::isAtEndOfMacroExpansion( + FoundEndLocExpansion, SM, PP.getLangOpts())); + + if (AttrStartIsInMacro && AttrEndIsInMacro) + return true; + } + } + + return false; +} + /// ParseGNUAttributes - Parse a non-empty attributes list. /// /// [GNU] attributes: @@ -133,7 +188,10 @@ assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!"); while (Tok.is(tok::kw___attribute)) { - ConsumeToken(); + SourceLocation AttrTokLoc = ConsumeToken(); + unsigned OldNumAttrs = attrs.size(); + unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0; + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "attribute")) { SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ; @@ -201,6 +259,25 @@ SkipUntil(tok::r_paren, StopAtSemi); if (endLoc) *endLoc = Loc; + + // If this was declared in a macro, attach the macro IdentifierInfo to the + // parsed attribute. + SourceLocation StartLoc, EndLoc; + if (FindLocsWithCommonFileID(PP, AttrTokLoc, Loc, StartLoc, EndLoc)) { + auto &SrcMgr = PP.getSourceManager(); + CharSourceRange ExpansionRange = SrcMgr.getExpansionRange(StartLoc); + StringRef name = + Lexer::getSourceText(ExpansionRange, SrcMgr, PP.getLangOpts()); + IdentifierInfo *MacroII = PP.getIdentifierInfo(name); + + for (unsigned i = OldNumAttrs; i < attrs.size(); ++i) + attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin()); + + if (LateAttrs) { + for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i) + (*LateAttrs)[i]->MacroII = MacroII; + } + } } } Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -2134,6 +2134,7 @@ case Type::Attributed: case Type::SubstTemplateTypeParm: case Type::PackExpansion: + case Type::MacroQualified: // Keep walking after single level desugaring. type = type.getSingleStepDesugaredType(getContext()); break; Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -2767,6 +2767,9 @@ case Type::Paren: T = cast<ParenType>(T)->getInnerType(); break; + case Type::MacroQualified: + T = cast<MacroQualifiedType>(T)->getUnderlyingType(); + break; case Type::SubstTemplateTypeParm: T = cast<SubstTemplateTypeParmType>(T)->getReplacementType(); break; @@ -2946,6 +2949,7 @@ case Type::DeducedTemplateSpecialization: case Type::Elaborated: case Type::Paren: + case Type::MacroQualified: case Type::SubstTemplateTypeParm: case Type::TypeOfExpr: case Type::TypeOf: Index: clang/lib/AST/TypePrinter.cpp =================================================================== --- clang/lib/AST/TypePrinter.cpp +++ clang/lib/AST/TypePrinter.cpp @@ -104,6 +104,9 @@ bool HasEmptyPlaceHolder = false; bool InsideCCAttribute = false; + // Set for preventing printing of macros with the same name. + llvm::StringSet<> PrintedMacros; + public: explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0) : Policy(Policy), Indentation(Indentation) {} @@ -259,6 +262,7 @@ case Type::Paren: case Type::PackExpansion: case Type::SubstTemplateTypeParm: + case Type::MacroQualified: CanPrefixQualifiers = false; break; @@ -963,6 +967,29 @@ printTypeSpec(T->getDecl(), OS); } +void TypePrinter::printMacroQualifiedBefore(const MacroQualifiedType *T, + raw_ostream &OS) { + StringRef MacroName = T->getMacroIdentifier()->getName(); + bool PrintedMacro = PrintedMacros.find(MacroName) != PrintedMacros.end(); + + if (!PrintedMacro) { + OS << MacroName << " "; + PrintedMacros.insert(MacroName); + } + + // Since this type is meant to print the macro instead of the whole attribute, + // we trim any attributes and go directly to the original modified type. + printBefore(T->getUnqualifiedType(), OS); + + if (!PrintedMacro) + PrintedMacros.erase(MacroName); +} + +void TypePrinter::printMacroQualifiedAfter(const MacroQualifiedType *T, + raw_ostream &OS) { + printAfter(T->getUnqualifiedType(), OS); +} + void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {} void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T, Index: clang/lib/AST/Type.cpp =================================================================== --- clang/lib/AST/Type.cpp +++ clang/lib/AST/Type.cpp @@ -954,6 +954,18 @@ return Ctx.getParenType(innerType); } + QualType VisitMacroQualifiedType(const MacroQualifiedType *T) { + QualType innerType = recurse(T->getUnderlyingType()); + if (innerType.isNull()) + return {}; + + if (innerType.getAsOpaquePtr() == T->getUnderlyingType().getAsOpaquePtr()) + return QualType(T, 0); + + return Ctx.getMacroQualifiedType(innerType, T->getMacroIdentifier(), + T->getExpansionLoc()); + } + TRIVIAL_TYPE_CLASS(Typedef) TRIVIAL_TYPE_CLASS(ObjCTypeParam) @@ -1712,6 +1724,10 @@ return Visit(T->getModifiedType()); } + Type *VisitMacroQualifiedType(const MacroQualifiedType *T) { + return Visit(T->getUnderlyingType()); + } + Type *VisitAdjustedType(const AdjustedType *T) { return Visit(T->getOriginalType()); } @@ -3081,6 +3097,12 @@ return getDecl()->getUnderlyingType(); } +QualType MacroQualifiedType::desugar() const { return getUnderlyingType(); } + +QualType MacroQualifiedType::getUnqualifiedType() const { + return cast<AttributedType>(getUnderlyingType())->getModifiedType(); +} + TypeOfExprType::TypeOfExprType(Expr *E, QualType can) : Type(TypeOfExpr, can, E->isTypeDependent(), E->isInstantiationDependent(), Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -1940,6 +1940,7 @@ case Type::ObjCTypeParam: case Type::Atomic: case Type::Pipe: + case Type::MacroQualified: llvm_unreachable("type is illegal as a nested name specifier"); case Type::SubstTemplateTypeParmPack: Index: clang/lib/AST/ASTStructuralEquivalence.cpp =================================================================== --- clang/lib/AST/ASTStructuralEquivalence.cpp +++ clang/lib/AST/ASTStructuralEquivalence.cpp @@ -595,6 +595,13 @@ return false; break; + case Type::MacroQualified: + if (!IsStructurallyEquivalent( + Context, cast<MacroQualifiedType>(T1)->getUnderlyingType(), + cast<MacroQualifiedType>(T2)->getUnderlyingType())) + return false; + break; + case Type::Typedef: if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(), cast<TypedefType>(T2)->getDecl())) Index: clang/lib/AST/ASTDiagnostic.cpp =================================================================== --- clang/lib/AST/ASTDiagnostic.cpp +++ clang/lib/AST/ASTDiagnostic.cpp @@ -41,6 +41,11 @@ QT = PT->desugar(); continue; } + // ... or a macro defined type ... + if (const MacroQualifiedType *MDT = dyn_cast<MacroQualifiedType>(Ty)) { + QT = MDT->desugar(); + continue; + } // ...or a substituted template type parameter ... if (const SubstTemplateTypeParmType *ST = dyn_cast<SubstTemplateTypeParmType>(Ty)) { Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -2056,6 +2056,10 @@ case Type::Paren: return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr()); + case Type::MacroQualified: + return getTypeInfo( + cast<MacroQualifiedType>(T)->getUnderlyingType().getTypePtr()); + case Type::ObjCTypeParam: return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr()); @@ -3937,7 +3941,7 @@ QualType canon = getCanonicalType(equivalentType); type = new (*this, TypeAlignment) - AttributedType(canon, attrKind, modifiedType, equivalentType); + AttributedType(canon, attrKind, modifiedType, equivalentType); Types.push_back(type); AttributedTypes.InsertNode(type, insertPos); @@ -4218,6 +4222,19 @@ return QualType(T, 0); } +QualType ASTContext::getMacroQualifiedType(QualType UnderlyingTy, + const IdentifierInfo *MacroII, + SourceLocation ExpansionLoc) const { + QualType Canon = UnderlyingTy; + if (!Canon.isCanonical()) + Canon = getCanonicalType(UnderlyingTy); + + auto *newType = new (*this, TypeAlignment) + MacroQualifiedType(UnderlyingTy, Canon, MacroII, ExpansionLoc); + Types.push_back(newType); + return QualType(newType, 0); +} + QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, Index: clang/lib/ARCMigrate/TransGCAttrs.cpp =================================================================== --- clang/lib/ARCMigrate/TransGCAttrs.cpp +++ clang/lib/ARCMigrate/TransGCAttrs.cpp @@ -68,6 +68,9 @@ if (handleAttr(Attr, D)) break; TL = Attr.getModifiedLoc(); + } else if (MacroQualifiedTypeLoc MDTL = + TL.getAs<MacroQualifiedTypeLoc>()) { + TL = MDTL.getInnerLoc(); } else if (ArrayTypeLoc Arr = TL.getAs<ArrayTypeLoc>()) { TL = Arr.getElementLoc(); } else if (PointerTypeLoc PT = TL.getAs<PointerTypeLoc>()) { Index: clang/include/clang/Serialization/ASTBitCodes.h =================================================================== --- clang/include/clang/Serialization/ASTBitCodes.h +++ clang/include/clang/Serialization/ASTBitCodes.h @@ -1173,7 +1173,10 @@ TYPE_DEPENDENT_ADDRESS_SPACE = 47, /// A dependentSizedVectorType record. - TYPE_DEPENDENT_SIZED_VECTOR = 48 + TYPE_DEPENDENT_SIZED_VECTOR = 48, + + /// A type defined in a macro. + TYPE_MACRO_DEFINED = 49 }; /// The type IDs for special types constructed by semantic Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -3420,7 +3420,7 @@ // Check if there is an explicit attribute, but only look through parens. // The intent is to look for an attribute on the current declarator, but not // one that came from a typedef. - bool hasExplicitCallingConv(QualType &T); + bool hasExplicitCallingConv(QualType T); /// Get the outermost AttributedType node that sets a calling convention. /// Valid types should not have multiple attributes with different CCs. Index: clang/include/clang/Sema/ParsedAttr.h =================================================================== --- clang/include/clang/Sema/ParsedAttr.h +++ clang/include/clang/Sema/ParsedAttr.h @@ -167,6 +167,8 @@ private: IdentifierInfo *AttrName; IdentifierInfo *ScopeName; + IdentifierInfo *MacroII = nullptr; + SourceLocation MacroExpansionLoc; SourceRange AttrRange; SourceLocation ScopeLoc; SourceLocation EllipsisLoc; @@ -538,6 +540,27 @@ return getPropertyDataBuffer().SetterId; } + /// Set the macro identifier info object that this parsed attribute was + /// declared in if it was declared in a macro. Also set the expansion location + /// of the macro. + void setMacroIdentifier(IdentifierInfo *MacroName, SourceLocation Loc) { + MacroII = MacroName; + MacroExpansionLoc = Loc; + } + + /// Returns true if this attribute was declared in a macro. + bool hasMacroIdentifier() const { return MacroII != nullptr; } + + /// Return the macro identifier if this attribute was declared in a macro. + /// nullptr is returned if it was not declared in a macro. + IdentifierInfo *getMacroIdentifier() const { return MacroII; } + + SourceLocation getMacroExpansionLoc() const { + assert(hasMacroIdentifier() && "Can only get the macro expansion location " + "if this attribute has a macro identifier."); + return MacroExpansionLoc; + } + /// Get an index into the attribute spelling list /// defined in Attr.td. This index is used by an attribute /// to pretty print itself. Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -1124,6 +1124,7 @@ Parser *Self; CachedTokens Toks; IdentifierInfo &AttrName; + IdentifierInfo *MacroII = nullptr; SourceLocation AttrNameLoc; SmallVector<Decl*, 2> Decls; Index: clang/include/clang/AST/TypeNodes.def =================================================================== --- clang/include/clang/AST/TypeNodes.def +++ clang/include/clang/AST/TypeNodes.def @@ -82,6 +82,7 @@ DEPENDENT_TYPE(UnresolvedUsing, Type) NON_CANONICAL_TYPE(Paren, Type) NON_CANONICAL_TYPE(Typedef, Type) +NON_CANONICAL_TYPE(MacroQualified, Type) NON_CANONICAL_TYPE(Adjusted, Type) NON_CANONICAL_TYPE(Decayed, AdjustedType) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) Index: clang/include/clang/AST/TypeLoc.h =================================================================== --- clang/include/clang/AST/TypeLoc.h +++ clang/include/clang/AST/TypeLoc.h @@ -173,6 +173,9 @@ TypeLoc IgnoreParens() const; + /// Strips MacroDefinitionTypeLocs from a type location. + TypeLoc IgnoreMacroDefinitions() const; + /// Find a type with the location of an explicit type qualifier. /// /// The result, if non-null, will be one of: @@ -1080,6 +1083,37 @@ } }; +struct MacroQualifiedLocInfo {}; + +class MacroQualifiedTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, MacroQualifiedTypeLoc, + MacroQualifiedType, MacroQualifiedLocInfo> { +public: + void initializeLocal(ASTContext &Context, SourceLocation Loc) {} // Do nothing + + TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } + + const IdentifierInfo *getMacroIdentifier() const { + return getTypePtr()->getMacroIdentifier(); + } + + SourceLocation getExpansionLoc() const { + return getTypePtr()->getExpansionLoc(); + } + + QualType getInnerType() const { return getTypePtr()->getUnderlyingType(); } + + SourceRange getLocalSourceRange() const { + return getInnerLoc().getLocalSourceRange(); + } + + unsigned getLocalDataSize() const { + // sizeof(MacroQualifiedLocInfo) is 1, but we don't need its address to be + // unique anyway. TypeLocBuilder can't handle data sizes of 1. + return 0; // No data. + } +}; + struct ParenLocInfo { SourceLocation LParenLoc; SourceLocation RParenLoc; @@ -2289,6 +2323,8 @@ Cur = ETL.getNamedTypeLoc(); else if (auto ATL = Cur.getAs<AdjustedTypeLoc>()) Cur = ATL.getOriginalLoc(); + else if (auto MQL = Cur.getAs<MacroQualifiedTypeLoc>()) + Cur = MQL.getInnerLoc(); else break; } Index: clang/include/clang/AST/Type.h =================================================================== --- clang/include/clang/AST/Type.h +++ clang/include/clang/AST/Type.h @@ -4171,6 +4171,43 @@ static bool classof(const Type *T) { return T->getTypeClass() == Typedef; } }; +/// Sugar type that represents a type that was defined in a macro. +class MacroQualifiedType : public Type { + friend class ASTContext; // ASTContext creates these. + + QualType UnderlyingTy; + const IdentifierInfo *MacroII; + SourceLocation ExpansionLoc; + + MacroQualifiedType(QualType UnderlyingTy, QualType CanonTy, + const IdentifierInfo *MacroII, SourceLocation ExpansionLoc) + : Type(MacroQualified, CanonTy, UnderlyingTy->isDependentType(), + UnderlyingTy->isInstantiationDependentType(), + UnderlyingTy->isVariablyModifiedType(), + UnderlyingTy->containsUnexpandedParameterPack()), + UnderlyingTy(UnderlyingTy), MacroII(MacroII), + ExpansionLoc(ExpansionLoc) { + assert(isa<AttributedType>(UnderlyingTy) && + "Expected a macro qualified type to only wrap attributed types."); + } + +public: + const IdentifierInfo *getMacroIdentifier() const { return MacroII; } + QualType getUnderlyingType() const { return UnderlyingTy; } + SourceLocation getExpansionLoc() const { return ExpansionLoc; } + + /// Return this attributed type's modified type with no qualifiers attached to + /// it. + QualType getUnqualifiedType() const; + + bool isSugared() const { return true; } + QualType desugar() const; + + static bool classof(const Type *T) { + return T->getTypeClass() == MacroQualified; + } +}; + /// Represents a `typeof` (or __typeof__) expression (a GCC extension). class TypeOfExprType : public Type { Expr *TOExpr; @@ -6792,6 +6829,8 @@ Ty = P->desugar().getTypePtr(); else if (const auto *A = dyn_cast<AdjustedType>(Ty)) Ty = A->desugar().getTypePtr(); + else if (const auto *M = dyn_cast<MacroQualifiedType>(Ty)) + Ty = M->desugar().getTypePtr(); else break; } Index: clang/include/clang/AST/RecursiveASTVisitor.h =================================================================== --- clang/include/clang/AST/RecursiveASTVisitor.h +++ clang/include/clang/AST/RecursiveASTVisitor.h @@ -1065,6 +1065,9 @@ DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); }) +DEF_TRAVERSE_TYPE(MacroQualifiedType, + { TRY_TO(TraverseType(T->getUnderlyingType())); }) + DEF_TRAVERSE_TYPE(ElaboratedType, { if (T->getQualifier()) { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); @@ -1308,6 +1311,9 @@ DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) +DEF_TRAVERSE_TYPELOC(MacroQualifiedType, + { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) + DEF_TRAVERSE_TYPELOC(AttributedType, { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -1451,6 +1451,10 @@ QualType getParenType(QualType NamedType) const; + QualType getMacroQualifiedType(QualType UnderlyingTy, + const IdentifierInfo *MacroII, + SourceLocation ExpansionLoc) const; + QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, TagDecl *OwnedTagDecl = nullptr) const;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits