leonardchan updated this revision to Diff 183242.
leonardchan added a comment.
- Rebase after D55447 <https://reviews.llvm.org/D55447>
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/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/TypeLoc.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/SemaCUDA/qualifiers.cu
clang/test/SemaCXX/attr-require-constant-initialization.cpp
clang/test/SemaObjC/externally-retained.m
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::VisitMacroDefinedTypeLoc(MacroDefinedTypeLoc TL) {
+ return Visit(TL.getInnerLoc());
+}
+
bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
return Visit(TL.getPointeeLoc());
}
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/SemaCXX/attr-require-constant-initialization.cpp
===================================================================
--- clang/test/SemaCXX/attr-require-constant-initialization.cpp
+++ clang/test/SemaCXX/attr-require-constant-initialization.cpp
@@ -103,7 +103,7 @@
ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
#if __cplusplus >= 201103L
-// expected-note@-3 {{non-literal type 'const NonLit' cannot be used in a constant expression}}
+// expected-note@-3 {{non-literal type 'NonLit const' cannot be used in a constant expression}}
#else
// expected-note@-5 {{subexpression not valid in a constant expression}}
#endif
Index: clang/test/SemaCUDA/qualifiers.cu
===================================================================
--- clang/test/SemaCUDA/qualifiers.cu
+++ clang/test/SemaCUDA/qualifiers.cu
@@ -20,16 +20,16 @@
#if defined(__CUDA_ARCH__)
// NVPTX does not support TLS
__device__ int __thread device_tls_var; // expected-error {{thread-local storage is not supported for the current target}}
-// CHECK-DEVICE: device_tls_var 'int' tls
+// CHECK-DEVICE: device_tls_var 'int':'int' tls
__shared__ int __thread shared_tls_var; // expected-error {{thread-local storage is not supported for the current target}}
-// CHECK-DEVICE: shared_tls_var 'int' tls
+// CHECK-DEVICE: shared_tls_var 'int':'int' tls
#else
// Device-side vars should not produce any errors during host-side
// compilation.
__device__ int __thread device_tls_var;
-// CHECK-HOST: device_tls_var 'int' tls
+// CHECK-HOST: device_tls_var 'int':'int' tls
__shared__ int __thread shared_tls_var;
-// CHECK-HOST: shared_tls_var 'int' tls
+// CHECK-HOST: shared_tls_var 'int':'int' tls
#endif
__global__ void g1(int x) {}
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,39 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+#define AS1 __attribute__((address_space(1)))
+#define AS2 __attribute__((address_space(2), annotate("foo")))
+
+#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}}
+}
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 wether 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,12 @@
Code = TYPE_PAREN;
}
+void ASTTypeWriter::VisitMacroDefinedType(const MacroDefinedType *T) {
+ Record.AddTypeRef(T->getUnderlyingType());
+ Record.AddIdentifierRef(T->getMacroIdentifier());
+ Code = TYPE_MACRO_DEFINED;
+}
+
void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
Record.push_back(T->getKeyword());
Record.AddNestedNameSpecifier(T->getQualifier());
@@ -802,6 +808,8 @@
Record.AddSourceLocation(TL.getRParenLoc());
}
+void TypeLocWriter::VisitMacroDefinedTypeLoc(MacroDefinedTypeLoc TL) {}
+
void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
Record.AddSourceLocation(TL.getElaboratedKeywordLoc());
Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
@@ -1219,6 +1227,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,16 @@
return Context.getParenType(InnerType);
}
+ case TYPE_MACRO_DEFINED: {
+ if (Record.size() != 2) {
+ Error("incorrect encoding of macro defined type");
+ return QualType();
+ }
+ QualType UnderlyingTy = readType(*Loc.F, Record, Idx);
+ IdentifierInfo *MacroII = GetIdentifierInfo(*Loc.F, Record, Idx);
+ return Context.getMacroDefinedType(UnderlyingTy, MacroII);
+ }
+
case TYPE_PACK_EXPANSION: {
if (Record.size() != 2) {
Error("incorrect encoding of pack expansion type");
@@ -6499,6 +6509,8 @@
// nothing to do
}
+void TypeLocReader::VisitMacroDefinedTypeLoc(MacroDefinedTypeLoc 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,11 @@
return SemaRef.Context.getTypeDeclType(Typedef);
}
+ /// Build a new MacroDefined type.
+ QualType RebuildMacroDefinedType(QualType T, const IdentifierInfo *MacroII) {
+ return SemaRef.Context.getMacroDefinedType(T, MacroII);
+ }
+
/// Build a new class/struct/union type.
QualType RebuildRecordType(RecordDecl *Record) {
return SemaRef.Context.getTypeDeclType(Record);
@@ -6159,6 +6164,26 @@
return Result;
}
+template <typename Derived>
+QualType
+TreeTransform<Derived>::TransformMacroDefinedType(TypeLocBuilder &TLB,
+ MacroDefinedTypeLoc 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().RebuildMacroDefinedType(Inner, TL.getMacroIdentifier());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ TLB.push<MacroDefinedTypeLoc>(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 VisitMacroDefinedTypeLoc(MacroDefinedTypeLoc TL) {}
void VisitTypeLoc(TypeLoc TL) {
llvm_unreachable("unsupported TypeLoc kind in declarator!");
@@ -5696,6 +5698,9 @@
CurrTL = ATL.getValueLoc().getUnqualifiedLoc();
}
+ while (MacroDefinedTypeLoc TL = CurrTL.getAs<MacroDefinedTypeLoc>())
+ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+
while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
fillAttributedTypeLoc(TL, State);
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
@@ -6959,11 +6964,11 @@
}
bool Sema::hasExplicitCallingConv(QualType &T) {
- QualType R = T.IgnoreParens();
+ QualType R = T.IgnoreParens().IgnoreMacroDefinitions();
while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
if (AT->isCallingConv())
return true;
- R = AT->getModifiedType().IgnoreParens();
+ R = AT->getModifiedType().IgnoreParens().IgnoreMacroDefinitions();
}
return false;
}
@@ -7365,6 +7370,7 @@
// over that.
ParsedAttributesView AttrsCopy{attrs};
+ llvm::StringSet<> FoundMacros;
state.setParsedNoDeref(false);
for (ParsedAttr &attr : AttrsCopy) {
@@ -7543,6 +7549,15 @@
distributeFunctionTypeAttr(state, attr, type);
break;
}
+
+ // Handle attributes that are defined in a macro.
+ if (attr.hasMacroIdentifier() && !type.getQualifiers().hasObjCLifetime()) {
+ const IdentifierInfo *MacroII = attr.getMacroIdentifier();
+ if (FoundMacros.find(MacroII->getName()) == FoundMacros.end()) {
+ type = state.getSema().Context.getMacroDefinedType(type, MacroII);
+ FoundMacros.insert(MacroII->getName());
+ }
+ }
}
if (!state.getSema().getLangOpts().OpenCL ||
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3386,9 +3386,12 @@
}
TypeLoc Sema::getReturnTypeLoc(FunctionDecl *FD) const {
- TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
+ TypeLoc TL = FD->getTypeSourceInfo()
+ ->getTypeLoc()
+ .IgnoreParens()
+ .IgnoreMacroDefinitions();
while (auto ATL = TL.getAs<AttributedTypeLoc>())
- TL = ATL.getModifiedLoc().IgnoreParens();
+ TL = ATL.getModifiedLoc().IgnoreParens().IgnoreMacroDefinitions();
return TL.castAs<FunctionProtoTypeLoc>().getReturnLoc();
}
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::MacroDefined:
// Keep walking after single level desugaring.
T = T.getSingleStepDesugaredType(Context);
break;
@@ -13661,8 +13662,9 @@
// Look for an explicit signature in that function type.
FunctionProtoTypeLoc ExplicitSignature;
- if ((ExplicitSignature =
- Sig->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>())) {
+ if ((ExplicitSignature = Sig->getTypeLoc()
+ .IgnoreMacroDefinitions()
+ .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,50 @@
#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(SourceManager &SM, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ SourceLocation &FoundStartLocExpansion,
+ SourceLocation &FoundEndLocExpansion) {
+ llvm::SmallVector<SourceLocation, 8> StartLocs;
+
+ // 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;
+ return true;
+ }
+ }
+
+ return false;
+}
+
/// ParseGNUAttributes - Parse a non-empty attributes list.
///
/// [GNU] attributes:
@@ -133,7 +177,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 +248,33 @@
SkipUntil(tok::r_paren, StopAtSemi);
if (endLoc)
*endLoc = Loc;
+
+ // If this was declared in a macro, attatch the macro IdentifierInfo to the
+ // parsed attribute.
+ auto &SrcMgr = PP.getSourceManager();
+ SourceLocation StartLoc, EndLoc;
+ if (FindLocsWithCommonFileID(SrcMgr, AttrTokLoc, Loc, StartLoc, EndLoc)) {
+ bool AttrStartIsInMacro =
+ (StartLoc.isMacroID() && Lexer::isAtStartOfMacroExpansion(
+ StartLoc, SrcMgr, PP.getLangOpts()));
+ bool AttrEndIsInMacro =
+ (EndLoc.isMacroID() &&
+ Lexer::isAtEndOfMacroExpansion(EndLoc, SrcMgr, PP.getLangOpts()));
+
+ if (AttrStartIsInMacro && AttrEndIsInMacro) {
+ StringRef name = Lexer::getSourceText(
+ SrcMgr.getExpansionRange(StartLoc), SrcMgr, PP.getLangOpts());
+ IdentifierInfo *MacroII = PP.getIdentifierInfo(name);
+
+ for (unsigned i = OldNumAttrs; i < attrs.size(); ++i)
+ attrs[i].setMacroIdentifier(MacroII);
+
+ 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::MacroDefined:
// 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::MacroDefined:
+ T = cast<MacroDefinedType>(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::MacroDefined:
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
@@ -259,6 +259,7 @@
case Type::Paren:
case Type::PackExpansion:
case Type::SubstTemplateTypeParm:
+ case Type::MacroDefined:
CanPrefixQualifiers = false;
break;
@@ -963,6 +964,29 @@
printTypeSpec(T->getDecl(), OS);
}
+void TypePrinter::printMacroDefinedBefore(const MacroDefinedType *T,
+ raw_ostream &OS) {
+ if (const auto *AttrTy = dyn_cast<AttributedType>(T->getUnderlyingType())) {
+ if (AttrTy->getAttrKind() == attr::AddressSpace) {
+ OS << T->getMacroIdentifier()->getName() << " ";
+
+ // Remove the address_space qualifier so it does not get printed. We
+ // instead want to print the macro only.
+ SplitQualType SplitTy = AttrTy->getModifiedType().split();
+ Qualifiers Quals = SplitTy.Quals;
+ if (Quals.getAddressSpace() >= LangAS::FirstTargetAddressSpace)
+ Quals.removeAddressSpace();
+ return printBefore(SplitTy.Ty, Quals, OS);
+ }
+ }
+ printBefore(T->getUnderlyingType(), OS);
+}
+
+void TypePrinter::printMacroDefinedAfter(const MacroDefinedType *T,
+ raw_ostream &OS) {
+ printAfter(T->getUnderlyingType(), OS);
+}
+
void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {}
void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
Index: clang/lib/AST/TypeLoc.cpp
===================================================================
--- clang/lib/AST/TypeLoc.cpp
+++ clang/lib/AST/TypeLoc.cpp
@@ -405,6 +405,13 @@
return TL;
}
+TypeLoc TypeLoc::IgnoreMacroDefinitions() const {
+ TypeLoc Result = *this;
+ while (auto MDTL = Result.getAs<MacroDefinedTypeLoc>())
+ Result = MDTL.getInnerLoc();
+ return Result;
+}
+
SourceLocation TypeLoc::findNullabilityLoc() const {
if (auto ATL = getAs<AttributedTypeLoc>()) {
const Attr *A = ATL.getAttr();
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -379,6 +379,12 @@
return T;
}
+QualType QualType::IgnoreMacroDefinitions(QualType T) {
+ while (const auto *MDT = T->getAs<MacroDefinedType>())
+ T = MDT->getUnderlyingType();
+ return T;
+}
+
/// This will check for a T (which should be a Type which can act as
/// sugar, such as a TypedefType) by removing any existing sugar until it
/// reaches a T or a non-sugared type.
@@ -954,6 +960,17 @@
return Ctx.getParenType(innerType);
}
+ QualType VisitMacroDefinedType(const MacroDefinedType *T) {
+ QualType innerType = recurse(T->getUnderlyingType());
+ if (innerType.isNull())
+ return {};
+
+ if (innerType.getAsOpaquePtr() == T->getUnderlyingType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getMacroDefinedType(innerType, T->getMacroIdentifier());
+ }
+
TRIVIAL_TYPE_CLASS(Typedef)
TRIVIAL_TYPE_CLASS(ObjCTypeParam)
@@ -1712,6 +1729,10 @@
return Visit(T->getModifiedType());
}
+ Type *VisitMacroDefinedType(const MacroDefinedType *T) {
+ return Visit(T->getUnderlyingType());
+ }
+
Type *VisitAdjustedType(const AdjustedType *T) {
return Visit(T->getOriginalType());
}
@@ -3081,6 +3102,8 @@
return getDecl()->getUnderlyingType();
}
+QualType MacroDefinedType::desugar() const { return getUnderlyingType(); }
+
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::MacroDefined:
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
@@ -568,6 +568,13 @@
return false;
break;
+ case Type::MacroDefined:
+ if (!IsStructurallyEquivalent(
+ Context, cast<MacroDefinedType>(T1)->getUnderlyingType(),
+ cast<MacroDefinedType>(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 MacroDefinedType *MDT = dyn_cast<MacroDefinedType>(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::MacroDefined:
+ return getTypeInfo(
+ cast<MacroDefinedType>(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,18 @@
return QualType(T, 0);
}
+QualType ASTContext::getMacroDefinedType(QualType UnderlyingTy,
+ const IdentifierInfo *MacroII) const {
+ QualType Canon = UnderlyingTy;
+ if (!Canon.isCanonical())
+ Canon = getCanonicalType(UnderlyingTy);
+
+ auto *newType =
+ new (*this, TypeAlignment) MacroDefinedType(UnderlyingTy, Canon, MacroII);
+ 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,8 @@
if (handleAttr(Attr, D))
break;
TL = Attr.getModifiedLoc();
+ } else if (MacroDefinedTypeLoc MDTL = TL.getAs<MacroDefinedTypeLoc>()) {
+ 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/ParsedAttr.h
===================================================================
--- clang/include/clang/Sema/ParsedAttr.h
+++ clang/include/clang/Sema/ParsedAttr.h
@@ -167,6 +167,7 @@
private:
IdentifierInfo *AttrName;
IdentifierInfo *ScopeName;
+ IdentifierInfo *MacroII = nullptr;
SourceRange AttrRange;
SourceLocation ScopeLoc;
SourceLocation EllipsisLoc;
@@ -538,6 +539,17 @@
return getPropertyDataBuffer().SetterId;
}
+ /// Set the macro identifier info object that this parsed attribute was
+ /// declared in if it was declared in a macro.
+ void setMacroIdentifier(IdentifierInfo *MacroName) { MacroII = MacroName; }
+
+ /// 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; }
+
/// 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(MacroDefined, 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,33 @@
}
};
+struct MacroDefinedLocInfo {};
+
+class MacroDefinedTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, MacroDefinedTypeLoc,
+ MacroDefinedType, MacroDefinedLocInfo> {
+public:
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {} // Do nothing
+
+ TypeLoc getInnerLoc() const { return getInnerTypeLoc(); }
+
+ const IdentifierInfo *getMacroIdentifier() const {
+ return getTypePtr()->getMacroIdentifier();
+ }
+
+ QualType getInnerType() const { return getTypePtr()->getUnderlyingType(); }
+
+ SourceRange getLocalSourceRange() const {
+ return getInnerLoc().getLocalSourceRange();
+ }
+
+ unsigned getLocalDataSize() const {
+ // sizeof(MacroDefinedLocInfo) 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;
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -956,6 +956,13 @@
return *this;
}
+ /// Returns the specified type after dropping any outer MacroDefinedTypes.
+ QualType IgnoreMacroDefinitions() const {
+ if (isa<MacroDefinedType>(*this))
+ return QualType::IgnoreMacroDefinitions(*this);
+ return *this;
+ }
+
/// Indicate whether the specified types and qualifiers are identical.
friend bool operator==(const QualType &LHS, const QualType &RHS) {
return LHS.Value == RHS.Value;
@@ -1220,6 +1227,7 @@
static QualType getSingleStepDesugaredTypeImpl(QualType type,
const ASTContext &C);
static QualType IgnoreParens(QualType T);
+ static QualType IgnoreMacroDefinitions(QualType T);
static DestructionKind isDestructedTypeImpl(QualType type);
};
@@ -4171,6 +4179,33 @@
static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
};
+/// Sugar type that represents a type that was defined in a macro.
+class MacroDefinedType : public Type {
+ friend class ASTContext; // ASTContext creates these.
+
+ QualType UnderlyingTy;
+ const IdentifierInfo *MacroII;
+
+ MacroDefinedType(QualType UnderlyingTy, QualType CanonTy,
+ const IdentifierInfo *MacroII)
+ : Type(MacroDefined, CanonTy, UnderlyingTy->isDependentType(),
+ UnderlyingTy->isInstantiationDependentType(),
+ UnderlyingTy->isVariablyModifiedType(),
+ UnderlyingTy->containsUnexpandedParameterPack()),
+ UnderlyingTy(UnderlyingTy), MacroII(MacroII) {}
+
+public:
+ const IdentifierInfo *getMacroIdentifier() const { return MacroII; }
+ QualType getUnderlyingType() const { return UnderlyingTy; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == MacroDefined;
+ }
+};
+
/// Represents a `typeof` (or __typeof__) expression (a GCC extension).
class TypeOfExprType : public Type {
Expr *TOExpr;
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(MacroDefinedType,
+ { 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(MacroDefinedType,
+ { 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,9 @@
QualType getParenType(QualType NamedType) const;
+ QualType getMacroDefinedType(QualType UnderlyingTy,
+ const IdentifierInfo *MacroII) const;
+
QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS, QualType NamedType,
TagDecl *OwnedTagDecl = nullptr) const;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits