Changeset View
Changeset View
Standalone View
Standalone View
clang/lib/Sema/SemaAttr.cpp
Show First 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { | ||||
// FIXME: We should merge AddAlignmentAttributesForRecord with | // FIXME: We should merge AddAlignmentAttributesForRecord with | ||||
// AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes | // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes | ||||
// all active pragmas and applies them as attributes to class definitions. | // all active pragmas and applies them as attributes to class definitions. | ||||
if (VtorDispStack.CurrentValue != getLangOpts().VtorDispMode) | if (VtorDispStack.CurrentValue != getLangOpts().VtorDispMode) | ||||
RD->addAttr( | RD->addAttr( | ||||
MSVtorDispAttr::CreateImplicit(Context, VtorDispStack.CurrentValue)); | MSVtorDispAttr::CreateImplicit(Context, VtorDispStack.CurrentValue)); | ||||
} | } | ||||
template <typename Attribute> | |||||
static void addGslOwnerPointerAttributeIfNotExisting(ASTContext &Context, | |||||
CXXRecordDecl *Record) { | |||||
CXXRecordDecl *Canonical = Record->getCanonicalDecl(); | |||||
if (Canonical->hasAttr<OwnerAttr>() || Canonical->hasAttr<PointerAttr>()) | |||||
return; | |||||
Canonical->addAttr(::new (Context) Attribute(SourceRange{}, Context, | |||||
/*DerefType*/ nullptr, | |||||
/*Spelling=*/0)); | |||||
} | |||||
void Sema::addDefaultGslPointerAttribute(NamedDecl *ND, | |||||
CXXRecordDecl *UnderlyingRecord) { | |||||
if (!UnderlyingRecord) | |||||
return; | |||||
const auto *Parent = dyn_cast<CXXRecordDecl>(ND->getDeclContext()); | |||||
if (!Parent) | |||||
return; | |||||
static llvm::StringSet<> Containers{ | |||||
"array", | |||||
"basic_string", | |||||
"deque", | |||||
"forward_list", | |||||
"vector", | |||||
"list", | |||||
"map", | |||||
"multiset", | |||||
"multimap", | |||||
"priority_queue", | |||||
"queue", | |||||
"set", | |||||
"stack", | |||||
"unordered_set", | |||||
"unordered_map", | |||||
"unordered_multiset", | |||||
"unordered_multimap", | |||||
}; | |||||
static llvm::StringSet<> Iterators{"iterator", "const_iterator", | |||||
"reverse_iterator", | |||||
"const_reverse_iterator"}; | |||||
if (Parent->isInStdNamespace() && Iterators.count(ND->getName()) && | |||||
Containers.count(Parent->getName())) | |||||
addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, | |||||
UnderlyingRecord); | |||||
} | |||||
void Sema::addDefaultGslPointerAttribute(TypedefNameDecl *TD) { | |||||
QualType Canonical = TD->getUnderlyingType().getCanonicalType(); | |||||
CXXRecordDecl *RD = Canonical->getAsCXXRecordDecl(); | |||||
if (!RD) { | |||||
if (auto *TST = | |||||
dyn_cast<TemplateSpecializationType>(Canonical.getTypePtr())) { | |||||
RD = dyn_cast<CXXRecordDecl>( | |||||
TST->getTemplateName().getAsTemplateDecl()->getTemplatedDecl()); | |||||
} | |||||
} | |||||
addDefaultGslPointerAttribute(TD, RD); | |||||
} | |||||
void Sema::addDefaultGslOwnerPointerAttribute(CXXRecordDecl *Record) { | |||||
static llvm::StringSet<> StdOwners{ | |||||
"any", | |||||
"array", | |||||
"basic_regex", | |||||
"basic_string", | |||||
"deque", | |||||
"forward_list", | |||||
"vector", | |||||
"list", | |||||
"map", | |||||
"multiset", | |||||
"multimap", | |||||
"optional", | |||||
"priority_queue", | |||||
"queue", | |||||
"set", | |||||
"stack", | |||||
"unique_ptr", | |||||
"unordered_set", | |||||
"unordered_map", | |||||
"unordered_multiset", | |||||
"unordered_multimap", | |||||
"variant", | |||||
}; | |||||
static llvm::StringSet<> StdPointers{ | |||||
"basic_string_view", | |||||
"reference_wrapper", | |||||
"regex_iterator", | |||||
}; | |||||
if (!Record->getIdentifier()) | |||||
return; | |||||
// Handle classes that directly appear in std namespace. | |||||
if (Record->isInStdNamespace()) { | |||||
CXXRecordDecl *Canonical = Record->getCanonicalDecl(); | |||||
if (Canonical->hasAttr<OwnerAttr>() || Canonical->hasAttr<PointerAttr>()) | |||||
return; | |||||
if (StdOwners.count(Record->getName())) | |||||
addGslOwnerPointerAttributeIfNotExisting<OwnerAttr>(Context, Record); | |||||
else if (StdPointers.count(Record->getName())) | |||||
addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, Record); | |||||
return; | |||||
} | |||||
// Handle nested classes that could be a gsl::Pointer. | |||||
addDefaultGslPointerAttribute(Record, Record); | |||||
} | |||||
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, | void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, | ||||
SourceLocation PragmaLoc) { | SourceLocation PragmaLoc) { | ||||
PragmaMsStackAction Action = Sema::PSK_Reset; | PragmaMsStackAction Action = Sema::PSK_Reset; | ||||
unsigned Alignment = 0; | unsigned Alignment = 0; | ||||
switch (Kind) { | switch (Kind) { | ||||
// For all targets we support native and natural are the same. | // For all targets we support native and natural are the same. | ||||
// | // | ||||
// FIXME: This is not true on Darwin/PPC. | // FIXME: This is not true on Darwin/PPC. | ||||
▲ Show 20 Lines • Show All 775 Lines • Show Last 20 Lines |