Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
clang/lib/Sema/SemaLookup.cpp
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
#include "llvm/Support/ErrorHandling.h" | #include "llvm/Support/ErrorHandling.h" | ||||
#include <algorithm> | #include <algorithm> | ||||
#include <iterator> | #include <iterator> | ||||
#include <list> | #include <list> | ||||
#include <set> | #include <set> | ||||
#include <utility> | #include <utility> | ||||
#include <vector> | #include <vector> | ||||
static inline clang::QualType GetFloat16Type(clang::ASTContext &Context); | |||||
#include "OpenCLBuiltins.inc" | #include "OpenCLBuiltins.inc" | ||||
#include "SPIRVBuiltins.inc" | |||||
using namespace clang; | using namespace clang; | ||||
using namespace sema; | using namespace sema; | ||||
namespace { | namespace { | ||||
class UnqualUsingEntry { | class UnqualUsingEntry { | ||||
const DeclContext *Nominated; | const DeclContext *Nominated; | ||||
const DeclContext *CommonAncestor; | const DeclContext *CommonAncestor; | ||||
▲ Show 20 Lines • Show All 613 Lines • ▼ Show 20 Lines | |||||
LLVM_DUMP_METHOD void LookupResult::dump() { | LLVM_DUMP_METHOD void LookupResult::dump() { | ||||
llvm::errs() << "lookup results for " << getLookupName().getAsString() | llvm::errs() << "lookup results for " << getLookupName().getAsString() | ||||
<< ":\n"; | << ":\n"; | ||||
for (NamedDecl *D : *this) | for (NamedDecl *D : *this) | ||||
D->dump(); | D->dump(); | ||||
} | } | ||||
static inline QualType GetFloat16Type(clang::ASTContext &Context) { | |||||
return Context.getLangOpts().OpenCL ? Context.HalfTy : Context.Float16Ty; | |||||
} | |||||
/// Diagnose a missing builtin type. | /// Diagnose a missing builtin type. | ||||
static QualType diagOpenCLBuiltinTypeError(Sema &S, llvm::StringRef TypeClass, | static QualType diagOpenCLBuiltinTypeError(Sema &S, llvm::StringRef TypeClass, | ||||
llvm::StringRef Name) { | llvm::StringRef Name) { | ||||
S.Diag(SourceLocation(), diag::err_opencl_type_not_found) | S.Diag(SourceLocation(), diag::err_opencl_type_not_found) | ||||
<< TypeClass << Name; | << TypeClass << Name; | ||||
return S.Context.VoidTy; | return S.Context.VoidTy; | ||||
} | } | ||||
Show All 18 Lines | static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name) { | ||||
if (Result.empty()) | if (Result.empty()) | ||||
return diagOpenCLBuiltinTypeError(S, "typedef", Name); | return diagOpenCLBuiltinTypeError(S, "typedef", Name); | ||||
TypedefNameDecl *Decl = Result.getAsSingle<TypedefNameDecl>(); | TypedefNameDecl *Decl = Result.getAsSingle<TypedefNameDecl>(); | ||||
if (!Decl) | if (!Decl) | ||||
return diagOpenCLBuiltinTypeError(S, "typedef", Name); | return diagOpenCLBuiltinTypeError(S, "typedef", Name); | ||||
return S.Context.getTypedefType(Decl); | return S.Context.getTypedefType(Decl); | ||||
} | } | ||||
/// Get the QualType instances of the return type and arguments for an OpenCL | /// Get the QualType instances of the return type and arguments for a ProgModel | ||||
/// builtin function signature. | /// builtin function signature. | ||||
/// \param S (in) The Sema instance. | /// \param Context (in) The Context instance. | ||||
/// \param OpenCLBuiltin (in) The signature currently handled. | /// \param Builtin (in) The signature currently handled. | ||||
/// \param GenTypeMaxCnt (out) Maximum number of types contained in a generic | /// \param GenTypeMaxCnt (out) Maximum number of types contained in a generic | ||||
/// type used as return type or as argument. | /// type used as return type or as argument. | ||||
/// Only meaningful for generic types, otherwise equals 1. | /// Only meaningful for generic types, otherwise equals 1. | ||||
/// \param RetTypes (out) List of the possible return types. | /// \param RetTypes (out) List of the possible return types. | ||||
/// \param ArgTypes (out) List of the possible argument types. For each | /// \param ArgTypes (out) List of the possible argument types. For each | ||||
/// argument, ArgTypes contains QualTypes for the Cartesian product | /// argument, ArgTypes contains QualTypes for the Cartesian product | ||||
/// of (vector sizes) x (types) . | /// of (vector sizes) x (types) . | ||||
static void GetQualTypesForOpenCLBuiltin( | template <typename ProgModel> | ||||
Sema &S, const OpenCLBuiltinStruct &OpenCLBuiltin, unsigned &GenTypeMaxCnt, | static void GetQualTypesForProgModelBuiltin( | ||||
SmallVector<QualType, 1> &RetTypes, | Sema &S, const typename ProgModel::BuiltinStruct &Builtin, | ||||
unsigned &GenTypeMaxCnt, SmallVector<QualType, 1> &RetTypes, | |||||
SmallVector<SmallVector<QualType, 1>, 5> &ArgTypes) { | SmallVector<SmallVector<QualType, 1>, 5> &ArgTypes) { | ||||
// Get the QualType instances of the return types. | // Get the QualType instances of the return types. | ||||
unsigned Sig = SignatureTable[OpenCLBuiltin.SigTableIndex]; | unsigned Sig = ProgModel::SignatureTable[Builtin.SigTableIndex]; | ||||
OCL2Qual(S, TypeTable[Sig], RetTypes); | ProgModel::Bultin2Qual(S, ProgModel::TypeTable[Sig], RetTypes); | ||||
GenTypeMaxCnt = RetTypes.size(); | GenTypeMaxCnt = RetTypes.size(); | ||||
// Get the QualType instances of the arguments. | // Get the QualType instances of the arguments. | ||||
// First type is the return type, skip it. | // First type is the return type, skip it. | ||||
for (unsigned Index = 1; Index < OpenCLBuiltin.NumTypes; Index++) { | for (unsigned Index = 1; Index < Builtin.NumTypes; Index++) { | ||||
SmallVector<QualType, 1> Ty; | SmallVector<QualType, 1> Ty; | ||||
OCL2Qual(S, TypeTable[SignatureTable[OpenCLBuiltin.SigTableIndex + Index]], | ProgModel::Bultin2Qual( | ||||
S, | |||||
ProgModel::TypeTable[ProgModel::SignatureTable[Builtin.SigTableIndex + | |||||
Index]], | |||||
Ty); | Ty); | ||||
GenTypeMaxCnt = (Ty.size() > GenTypeMaxCnt) ? Ty.size() : GenTypeMaxCnt; | GenTypeMaxCnt = (Ty.size() > GenTypeMaxCnt) ? Ty.size() : GenTypeMaxCnt; | ||||
ArgTypes.push_back(std::move(Ty)); | ArgTypes.push_back(std::move(Ty)); | ||||
} | } | ||||
} | } | ||||
/// Create a list of the candidate function overloads for an OpenCL builtin | /// Create a list of the candidate function overloads for a ProgModel builtin | ||||
/// function. | /// function. | ||||
/// \param Context (in) The ASTContext instance. | /// \param Context (in) The ASTContext instance. | ||||
/// \param GenTypeMaxCnt (in) Maximum number of types contained in a generic | /// \param GenTypeMaxCnt (in) Maximum number of types contained in a generic | ||||
/// type used as return type or as argument. | /// type used as return type or as argument. | ||||
/// Only meaningful for generic types, otherwise equals 1. | /// Only meaningful for generic types, otherwise equals 1. | ||||
/// \param FunctionList (out) List of FunctionTypes. | /// \param FunctionList (out) List of FunctionTypes. | ||||
/// \param RetTypes (in) List of the possible return types. | /// \param RetTypes (in) List of the possible return types. | ||||
/// \param ArgTypes (in) List of the possible types for the arguments. | /// \param ArgTypes (in) List of the possible types for the arguments. | ||||
static void GetOpenCLBuiltinFctOverloads( | static void GetProgModelBuiltinFctOverloads( | ||||
ASTContext &Context, unsigned GenTypeMaxCnt, | ASTContext &Context, unsigned GenTypeMaxCnt, | ||||
std::vector<QualType> &FunctionList, SmallVector<QualType, 1> &RetTypes, | std::vector<QualType> &FunctionList, SmallVector<QualType, 1> &RetTypes, | ||||
SmallVector<SmallVector<QualType, 1>, 5> &ArgTypes) { | SmallVector<SmallVector<QualType, 1>, 5> &ArgTypes, bool IsVariadic) { | ||||
FunctionProtoType::ExtProtoInfo PI( | FunctionProtoType::ExtProtoInfo PI( | ||||
Context.getDefaultCallingConvention(false, false, true)); | Context.getDefaultCallingConvention(false, false, true)); | ||||
PI.Variadic = false; | PI.Variadic = IsVariadic; | ||||
// Do not attempt to create any FunctionTypes if there are no return types, | // Do not attempt to create any FunctionTypes if there are no return types, | ||||
// which happens when a type belongs to a disabled extension. | // which happens when a type belongs to a disabled extension. | ||||
if (RetTypes.size() == 0) | if (RetTypes.size() == 0) | ||||
return; | return; | ||||
// Create FunctionTypes for each (gen)type. | // Create FunctionTypes for each (gen)type. | ||||
for (unsigned IGenType = 0; IGenType < GenTypeMaxCnt; IGenType++) { | for (unsigned IGenType = 0; IGenType < GenTypeMaxCnt; IGenType++) { | ||||
Show All 13 Lines | for (unsigned A = 0; A < ArgTypes.size(); A++) { | ||||
ArgList.push_back(ArgTypes[A][Idx]); | ArgList.push_back(ArgTypes[A][Idx]); | ||||
} | } | ||||
FunctionList.push_back(Context.getFunctionType( | FunctionList.push_back(Context.getFunctionType( | ||||
RetTypes[(RetTypes.size() != 1) ? IGenType : 0], ArgList, PI)); | RetTypes[(RetTypes.size() != 1) ? IGenType : 0], ArgList, PI)); | ||||
} | } | ||||
} | } | ||||
/// When trying to resolve a function name, if isOpenCLBuiltin() returns a | template <typename ProgModel> | ||||
/// non-null <Index, Len> pair, then the name is referencing an OpenCL | static bool isVersionInMask(const LangOptions &O, unsigned Mask); | ||||
template <> | |||||
bool isVersionInMask<OpenCLBuiltin>(const LangOptions &LO, unsigned Mask) { | |||||
return isOpenCLVersionContainedInMask(LO, Mask); | |||||
} | |||||
// SPIRV Builtins are always permitted, since all builtins are 'SPIRV_ALL'. We | |||||
// have no corresponding language option to check, so we always include them. | |||||
template <> | |||||
bool isVersionInMask<SPIRVBuiltin>(const LangOptions &LO, unsigned Mask) { | |||||
return true; | |||||
} | |||||
/// When trying to resolve a function name, if ProgModel::isBuiltin() returns a | |||||
/// non-null <Index, Len> pair, then the name is referencing a | |||||
/// builtin function. Add all candidate signatures to the LookUpResult. | /// builtin function. Add all candidate signatures to the LookUpResult. | ||||
/// | /// | ||||
/// \param S (in) The Sema instance. | /// \param S (in) The Sema instance. | ||||
/// \param LR (inout) The LookupResult instance. | /// \param LR (inout) The LookupResult instance. | ||||
/// \param II (in) The identifier being resolved. | /// \param II (in) The identifier being resolved. | ||||
/// \param FctIndex (in) Starting index in the BuiltinTable. | /// \param FctIndex (in) Starting index in the BuiltinTable. | ||||
/// \param Len (in) The signature list has Len elements. | /// \param Len (in) The signature list has Len elements. | ||||
static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, | template <typename ProgModel> | ||||
IdentifierInfo *II, | static void InsertBuiltinDeclarationsFromTable( | ||||
const unsigned FctIndex, | Sema &S, LookupResult &LR, IdentifierInfo *II, const unsigned FctIndex, | ||||
const unsigned Len) { | const unsigned Len, | ||||
std::function<void(const typename ProgModel::BuiltinStruct &, | |||||
FunctionDecl &)> | |||||
ProgModelFinalizer) { | |||||
// The builtin function declaration uses generic types (gentype). | // The builtin function declaration uses generic types (gentype). | ||||
bool HasGenType = false; | bool HasGenType = false; | ||||
// Maximum number of types contained in a generic type used as return type or | // Maximum number of types contained in a generic type used as return type or | ||||
// as argument. Only meaningful for generic types, otherwise equals 1. | // as argument. Only meaningful for generic types, otherwise equals 1. | ||||
unsigned GenTypeMaxCnt; | unsigned GenTypeMaxCnt; | ||||
ASTContext &Context = S.Context; | ASTContext &Context = S.Context; | ||||
for (unsigned SignatureIndex = 0; SignatureIndex < Len; SignatureIndex++) { | for (unsigned SignatureIndex = 0; SignatureIndex < Len; SignatureIndex++) { | ||||
const OpenCLBuiltinStruct &OpenCLBuiltin = | const typename ProgModel::BuiltinStruct &Builtin = | ||||
BuiltinTable[FctIndex + SignatureIndex]; | ProgModel::BuiltinTable[FctIndex + SignatureIndex]; | ||||
// Ignore this builtin function if it is not available in the currently | // Ignore this builtin function if it is not available in the currently | ||||
// selected language version. | // selected language version. | ||||
if (!isOpenCLVersionContainedInMask(Context.getLangOpts(), | if (!isVersionInMask<ProgModel>(Context.getLangOpts(), Builtin.Versions)) | ||||
OpenCLBuiltin.Versions)) | |||||
continue; | continue; | ||||
// Ignore this builtin function if it carries an extension macro that is | // Ignore this builtin function if it carries an extension macro that is | ||||
// not defined. This indicates that the extension is not supported by the | // not defined. This indicates that the extension is not supported by the | ||||
// target, so the builtin function should not be available. | // target, so the builtin function should not be available. | ||||
StringRef Extensions = FunctionExtensionTable[OpenCLBuiltin.Extension]; | StringRef Extensions = ProgModel::FunctionExtensionTable[Builtin.Extension]; | ||||
if (!Extensions.empty()) { | if (!Extensions.empty()) { | ||||
SmallVector<StringRef, 2> ExtVec; | SmallVector<StringRef, 2> ExtVec; | ||||
Extensions.split(ExtVec, " "); | Extensions.split(ExtVec, " "); | ||||
bool AllExtensionsDefined = true; | bool AllExtensionsDefined = true; | ||||
for (StringRef Ext : ExtVec) { | for (StringRef Ext : ExtVec) { | ||||
if (!S.getPreprocessor().isMacroDefined(Ext)) { | if (!S.getPreprocessor().isMacroDefined(Ext)) { | ||||
AllExtensionsDefined = false; | AllExtensionsDefined = false; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (!AllExtensionsDefined) | if (!AllExtensionsDefined) | ||||
continue; | continue; | ||||
} | } | ||||
SmallVector<QualType, 1> RetTypes; | SmallVector<QualType, 1> RetTypes; | ||||
SmallVector<SmallVector<QualType, 1>, 5> ArgTypes; | SmallVector<SmallVector<QualType, 1>, 5> ArgTypes; | ||||
// Obtain QualType lists for the function signature. | // Obtain QualType lists for the function signature. | ||||
GetQualTypesForOpenCLBuiltin(S, OpenCLBuiltin, GenTypeMaxCnt, RetTypes, | GetQualTypesForProgModelBuiltin<ProgModel>(S, Builtin, GenTypeMaxCnt, | ||||
ArgTypes); | RetTypes, ArgTypes); | ||||
if (GenTypeMaxCnt > 1) { | if (GenTypeMaxCnt > 1) { | ||||
HasGenType = true; | HasGenType = true; | ||||
} | } | ||||
// Create function overload for each type combination. | // Create function overload for each type combination. | ||||
std::vector<QualType> FunctionList; | std::vector<QualType> FunctionList; | ||||
GetOpenCLBuiltinFctOverloads(Context, GenTypeMaxCnt, FunctionList, RetTypes, | GetProgModelBuiltinFctOverloads(Context, GenTypeMaxCnt, FunctionList, | ||||
ArgTypes); | RetTypes, ArgTypes, Builtin.IsVariadic); | ||||
SourceLocation Loc = LR.getNameLoc(); | SourceLocation Loc = LR.getNameLoc(); | ||||
DeclContext *Parent = Context.getTranslationUnitDecl(); | DeclContext *Parent = Context.getTranslationUnitDecl(); | ||||
FunctionDecl *NewOpenCLBuiltin; | FunctionDecl *NewBuiltin; | ||||
for (const auto &FTy : FunctionList) { | for (const auto &FTy : FunctionList) { | ||||
NewOpenCLBuiltin = FunctionDecl::Create( | NewBuiltin = FunctionDecl::Create(Context, Parent, Loc, Loc, II, FTy, | ||||
Context, Parent, Loc, Loc, II, FTy, /*TInfo=*/nullptr, SC_Extern, | /*TInfo=*/nullptr, SC_Extern, | ||||
S.getCurFPFeatures().isFPConstrained(), false, | S.getCurFPFeatures().isFPConstrained(), | ||||
FTy->isFunctionProtoType()); | false, FTy->isFunctionProtoType()); | ||||
NewOpenCLBuiltin->setImplicit(); | NewBuiltin->setImplicit(); | ||||
// Create Decl objects for each parameter, adding them to the | // Create Decl objects for each parameter, adding them to the | ||||
// FunctionDecl. | // FunctionDecl. | ||||
const auto *FP = cast<FunctionProtoType>(FTy); | const auto *FP = cast<FunctionProtoType>(FTy); | ||||
SmallVector<ParmVarDecl *, 4> ParmList; | SmallVector<ParmVarDecl *, 4> ParmList; | ||||
for (unsigned IParm = 0, e = FP->getNumParams(); IParm != e; ++IParm) { | for (unsigned IParm = 0, e = FP->getNumParams(); IParm != e; ++IParm) { | ||||
ParmVarDecl *Parm = ParmVarDecl::Create( | ParmVarDecl *Parm = ParmVarDecl::Create( | ||||
Context, NewOpenCLBuiltin, SourceLocation(), SourceLocation(), | Context, NewBuiltin, SourceLocation(), SourceLocation(), nullptr, | ||||
nullptr, FP->getParamType(IParm), nullptr, SC_None, nullptr); | FP->getParamType(IParm), nullptr, SC_None, nullptr); | ||||
Parm->setScopeInfo(0, IParm); | Parm->setScopeInfo(0, IParm); | ||||
ParmList.push_back(Parm); | ParmList.push_back(Parm); | ||||
} | } | ||||
NewOpenCLBuiltin->setParams(ParmList); | NewBuiltin->setParams(ParmList); | ||||
// Add function attributes. | // Add function attributes. | ||||
if (OpenCLBuiltin.IsPure) | if (Builtin.IsPure) | ||||
NewOpenCLBuiltin->addAttr(PureAttr::CreateImplicit(Context)); | NewBuiltin->addAttr(PureAttr::CreateImplicit(Context)); | ||||
if (OpenCLBuiltin.IsConst) | if (Builtin.IsConst) | ||||
NewOpenCLBuiltin->addAttr(ConstAttr::CreateImplicit(Context)); | NewBuiltin->addAttr(ConstAttr::CreateImplicit(Context)); | ||||
if (OpenCLBuiltin.IsConv) | if (Builtin.IsConv) | ||||
NewOpenCLBuiltin->addAttr(ConvergentAttr::CreateImplicit(Context)); | NewBuiltin->addAttr(ConvergentAttr::CreateImplicit(Context)); | ||||
if (!S.getLangOpts().OpenCLCPlusPlus) | if (!S.getLangOpts().OpenCLCPlusPlus) | ||||
NewOpenCLBuiltin->addAttr(OverloadableAttr::CreateImplicit(Context)); | NewBuiltin->addAttr(OverloadableAttr::CreateImplicit(Context)); | ||||
LR.addDecl(NewOpenCLBuiltin); | ProgModelFinalizer(Builtin, *NewBuiltin); | ||||
LR.addDecl(NewBuiltin); | |||||
} | } | ||||
} | } | ||||
// If we added overloads, need to resolve the lookup result. | // If we added overloads, need to resolve the lookup result. | ||||
if (Len > 1 || HasGenType) | if (Len > 1 || HasGenType) | ||||
LR.resolveKind(); | LR.resolveKind(); | ||||
} | } | ||||
Show All 16 Lines | if (II) { | ||||
} else if (II == getASTContext().getTypePackElementName()) { | } else if (II == getASTContext().getTypePackElementName()) { | ||||
R.addDecl(getASTContext().getTypePackElementDecl()); | R.addDecl(getASTContext().getTypePackElementDecl()); | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
// Check if this is an OpenCL Builtin, and if so, insert its overloads. | // Check if this is an OpenCL Builtin, and if so, insert its overloads. | ||||
if (getLangOpts().OpenCL && getLangOpts().DeclareOpenCLBuiltins) { | if (getLangOpts().OpenCL && getLangOpts().DeclareOpenCLBuiltins) { | ||||
auto Index = isOpenCLBuiltin(II->getName()); | auto Index = OpenCLBuiltin::isBuiltin(II->getName()); | ||||
if (Index.first) { | if (Index.first) { | ||||
InsertOCLBuiltinDeclarationsFromTable(*this, R, II, Index.first - 1, | InsertBuiltinDeclarationsFromTable<OpenCLBuiltin>( | ||||
Index.second); | *this, R, II, Index.first - 1, Index.second, | ||||
[this](const OpenCLBuiltin::BuiltinStruct &OpenCLBuiltin, | |||||
FunctionDecl &NewOpenCLBuiltin) { | |||||
if (!this->getLangOpts().OpenCLCPlusPlus) | |||||
NewOpenCLBuiltin.addAttr( | |||||
OverloadableAttr::CreateImplicit(Context)); | |||||
}); | |||||
return true; | |||||
} | |||||
} | |||||
// Check if this is a SPIR-V Builtin, and if so, insert its overloads. | |||||
if (getLangOpts().DeclareSPIRVBuiltins) { | |||||
auto Index = SPIRVBuiltin::isBuiltin(II->getName()); | |||||
if (Index.first) { | |||||
InsertBuiltinDeclarationsFromTable<SPIRVBuiltin>( | |||||
*this, R, II, Index.first - 1, Index.second, | |||||
[this](const SPIRVBuiltin::BuiltinStruct &, | |||||
FunctionDecl &NewBuiltin) { | |||||
if (!this->getLangOpts().CPlusPlus) | |||||
NewBuiltin.addAttr(OverloadableAttr::CreateImplicit(Context)); | |||||
}); | |||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
// If this is a builtin on this (or all) targets, create the decl. | // If this is a builtin on this (or all) targets, create the decl. | ||||
if (unsigned BuiltinID = II->getBuiltinID()) { | if (unsigned BuiltinID = II->getBuiltinID()) { | ||||
// In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined | // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined | ||||
// library functions like 'malloc'. Instead, we'll just error. | // library functions like 'malloc'. Instead, we'll just error. | ||||
▲ Show 20 Lines • Show All 4,591 Lines • Show Last 20 Lines |