284 lines · cpp
1//===--- AttrImpl.cpp - Classes for representing attributes -----*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains out-of-line methods for Attr classes.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTContext.h"14#include "clang/AST/Attr.h"15#include "clang/AST/Expr.h"16#include "clang/AST/Type.h"17#include <optional>18using namespace clang;19 20void LoopHintAttr::printPrettyPragma(raw_ostream &OS,21 const PrintingPolicy &Policy) const {22 unsigned SpellingIndex = getAttributeSpellingListIndex();23 // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or24 // "nounroll" is already emitted as the pragma name.25 if (SpellingIndex == Pragma_nounroll ||26 SpellingIndex == Pragma_nounroll_and_jam)27 return;28 else if (SpellingIndex == Pragma_unroll ||29 SpellingIndex == Pragma_unroll_and_jam) {30 OS << ' ' << getValueString(Policy);31 return;32 }33 34 assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");35 OS << ' ' << getOptionName(option) << getValueString(Policy);36}37 38// Return a string containing the loop hint argument including the39// enclosing parentheses.40std::string LoopHintAttr::getValueString(const PrintingPolicy &Policy) const {41 std::string ValueName;42 llvm::raw_string_ostream OS(ValueName);43 OS << "(";44 if (state == Numeric)45 value->printPretty(OS, nullptr, Policy);46 else if (state == FixedWidth || state == ScalableWidth) {47 if (value) {48 value->printPretty(OS, nullptr, Policy);49 if (state == ScalableWidth)50 OS << ", scalable";51 } else if (state == ScalableWidth)52 OS << "scalable";53 else54 OS << "fixed";55 } else if (state == Enable)56 OS << "enable";57 else if (state == Full)58 OS << "full";59 else if (state == AssumeSafety)60 OS << "assume_safety";61 else62 OS << "disable";63 OS << ")";64 return ValueName;65}66 67// Return a string suitable for identifying this attribute in diagnostics.68std::string69LoopHintAttr::getDiagnosticName(const PrintingPolicy &Policy) const {70 unsigned SpellingIndex = getAttributeSpellingListIndex();71 if (SpellingIndex == Pragma_nounroll)72 return "#pragma nounroll";73 else if (SpellingIndex == Pragma_unroll)74 return "#pragma unroll" +75 (option == UnrollCount ? getValueString(Policy) : "");76 else if (SpellingIndex == Pragma_nounroll_and_jam)77 return "#pragma nounroll_and_jam";78 else if (SpellingIndex == Pragma_unroll_and_jam)79 return "#pragma unroll_and_jam" +80 (option == UnrollAndJamCount ? getValueString(Policy) : "");81 82 assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");83 return getOptionName(option) + getValueString(Policy);84}85 86void OMPDeclareSimdDeclAttr::printPrettyPragma(87 raw_ostream &OS, const PrintingPolicy &Policy) const {88 if (getBranchState() != BS_Undefined)89 OS << ' ' << ConvertBranchStateTyToStr(getBranchState());90 if (auto *E = getSimdlen()) {91 OS << " simdlen(";92 E->printPretty(OS, nullptr, Policy);93 OS << ")";94 }95 if (uniforms_size() > 0) {96 OS << " uniform";97 StringRef Sep = "(";98 for (auto *E : uniforms()) {99 OS << Sep;100 E->printPretty(OS, nullptr, Policy);101 Sep = ", ";102 }103 OS << ")";104 }105 alignments_iterator NI = alignments_begin();106 for (auto *E : aligneds()) {107 OS << " aligned(";108 E->printPretty(OS, nullptr, Policy);109 if (*NI) {110 OS << ": ";111 (*NI)->printPretty(OS, nullptr, Policy);112 }113 OS << ")";114 ++NI;115 }116 steps_iterator I = steps_begin();117 modifiers_iterator MI = modifiers_begin();118 for (auto *E : linears()) {119 OS << " linear(";120 if (*MI != OMPC_LINEAR_unknown)121 OS << getOpenMPSimpleClauseTypeName(llvm::omp::Clause::OMPC_linear, *MI)122 << "(";123 E->printPretty(OS, nullptr, Policy);124 if (*MI != OMPC_LINEAR_unknown)125 OS << ")";126 if (*I) {127 OS << ": ";128 (*I)->printPretty(OS, nullptr, Policy);129 }130 OS << ")";131 ++I;132 ++MI;133 }134}135 136void OMPDeclareTargetDeclAttr::printPrettyPragma(137 raw_ostream &OS, const PrintingPolicy &Policy) const {138 // Use fake syntax because it is for testing and debugging purpose only.139 if (getDevType() != DT_Any)140 OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";141 if (getMapType() != MT_To && getMapType() != MT_Enter)142 OS << ' ' << ConvertMapTypeTyToStr(getMapType());143 if (Expr *E = getIndirectExpr()) {144 OS << " indirect(";145 E->printPretty(OS, nullptr, Policy);146 OS << ")";147 } else if (getIndirect()) {148 OS << " indirect";149 }150}151 152std::optional<OMPDeclareTargetDeclAttr *>153OMPDeclareTargetDeclAttr::getActiveAttr(const ValueDecl *VD) {154 if (llvm::all_of(VD->redecls(), [](const Decl *D) { return !D->hasAttrs(); }))155 return std::nullopt;156 unsigned Level = 0;157 OMPDeclareTargetDeclAttr *FoundAttr = nullptr;158 for (const Decl *D : VD->redecls()) {159 for (auto *Attr : D->specific_attrs<OMPDeclareTargetDeclAttr>()) {160 if (Level <= Attr->getLevel()) {161 Level = Attr->getLevel();162 FoundAttr = Attr;163 }164 }165 }166 if (FoundAttr)167 return FoundAttr;168 return std::nullopt;169}170 171std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>172OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) {173 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);174 if (ActiveAttr)175 return (*ActiveAttr)->getMapType();176 return std::nullopt;177}178 179std::optional<OMPDeclareTargetDeclAttr::DevTypeTy>180OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) {181 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);182 if (ActiveAttr)183 return (*ActiveAttr)->getDevType();184 return std::nullopt;185}186 187std::optional<SourceLocation>188OMPDeclareTargetDeclAttr::getLocation(const ValueDecl *VD) {189 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);190 if (ActiveAttr)191 return (*ActiveAttr)->getRange().getBegin();192 return std::nullopt;193}194 195namespace clang {196llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo &TI);197llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo *TI);198}199 200void OMPDeclareVariantAttr::printPrettyPragma(201 raw_ostream &OS, const PrintingPolicy &Policy) const {202 if (const Expr *E = getVariantFuncRef()) {203 OS << "(";204 E->printPretty(OS, nullptr, Policy);205 OS << ")";206 }207 OS << " match(" << traitInfos << ")";208 209 auto PrintExprs = [&OS, &Policy](Expr **Begin, Expr **End) {210 for (Expr **I = Begin; I != End; ++I) {211 assert(*I && "Expected non-null Stmt");212 if (I != Begin)213 OS << ",";214 (*I)->printPretty(OS, nullptr, Policy);215 }216 };217 if (adjustArgsNothing_size()) {218 OS << " adjust_args(nothing:";219 PrintExprs(adjustArgsNothing_begin(), adjustArgsNothing_end());220 OS << ")";221 }222 if (adjustArgsNeedDevicePtr_size()) {223 OS << " adjust_args(need_device_ptr:";224 PrintExprs(adjustArgsNeedDevicePtr_begin(), adjustArgsNeedDevicePtr_end());225 OS << ")";226 }227 if (adjustArgsNeedDeviceAddr_size()) {228 OS << " adjust_args(need_device_addr:";229 PrintExprs(adjustArgsNeedDeviceAddr_begin(),230 adjustArgsNeedDeviceAddr_end());231 OS << ")";232 }233 234 auto PrintInteropInfo = [&OS](OMPInteropInfo *Begin, OMPInteropInfo *End) {235 for (OMPInteropInfo *I = Begin; I != End; ++I) {236 if (I != Begin)237 OS << ", ";238 OS << "interop(";239 OS << getInteropTypeString(I);240 OS << ")";241 }242 };243 if (appendArgs_size()) {244 OS << " append_args(";245 PrintInteropInfo(appendArgs_begin(), appendArgs_end());246 OS << ")";247 }248}249 250unsigned AlignedAttr::getAlignment(ASTContext &Ctx) const {251 assert(!isAlignmentDependent());252 if (getCachedAlignmentValue())253 return *getCachedAlignmentValue();254 255 // Handle alignmentType case.256 if (!isAlignmentExpr()) {257 QualType T = getAlignmentType()->getType();258 259 // C++ [expr.alignof]p3:260 // When alignof is applied to a reference type, the result is the261 // alignment of the referenced type.262 T = T.getNonReferenceType();263 264 if (T.getQualifiers().hasUnaligned())265 return Ctx.getCharWidth();266 267 return Ctx.getTypeAlignInChars(T.getTypePtr()).getQuantity() *268 Ctx.getCharWidth();269 }270 271 // Handle alignmentExpr case.272 if (alignmentExpr)273 return alignmentExpr->EvaluateKnownConstInt(Ctx).getZExtValue() *274 Ctx.getCharWidth();275 276 return Ctx.getTargetDefaultAlignForAttributeAligned();277}278 279StringLiteral *FormatMatchesAttr::getFormatString() const {280 return cast<StringLiteral>(getExpectedFormat());281}282 283#include "clang/AST/AttrImpl.inc"284