/** * Reports mismatch between buffer type and mpi datatype. * @param callExpr */ void MPIBugReporter::reportTypeMismatch( const CallExpr *callExpr, const std::pair<size_t, size_t> &idxPair, clang::QualType bufferType, std::string mpiType) const { auto adc = analysisManager_.getAnalysisDeclContext(currentFunctionDecl_); PathDiagnosticLocation location = PathDiagnosticLocation::createBegin( callExpr, bugReporter_.getSourceManager(), adc); // deref buffer type while (bufferType->isPointerType()) { bufferType = bufferType->getPointeeType(); } // remove qualifiers bufferType = bufferType.getUnqualifiedType(); SourceRange callRange = callExpr->getCallee()->getSourceRange(); std::string bugType{"type mismatch"}; std::string errorText{"Buffer type '" + bufferType.getAsString() + +"' and specified MPI type '" + mpiType + "' do not match. "}; llvm::SmallVector<SourceRange, 3> sourceRanges; sourceRanges.push_back(callRange); sourceRanges.push_back(callExpr->getArg(idxPair.first)->getSourceRange()); sourceRanges.push_back(callExpr->getArg(idxPair.second)->getSourceRange()); bugReporter_.EmitBasicReport(adc->getDecl(), &checkerBase_, bugType, MPIError, errorText, location, sourceRanges); }
// updates S.Ok; and, depending on Kind, possibly S.FnAccumulatorOk or S.FnOutConverterOk void RSExportReduce::checkVoidReturn(StateOfAnalyzeTranslationUnit &S, FnIdent Kind, clang::FunctionDecl *Fn) { slangAssert(Fn); const clang::QualType ReturnTy = Fn->getReturnType().getCanonicalType(); if (!ReturnTy->isVoidType()) { S.RSC.ReportError(Fn->getLocation(), "%0 must return void not '%1'") << S.DiagnosticDescription(getKey(Kind), Fn->getName()) << ReturnTy.getAsString(); notOk(S, Kind); } }
std::string GetTypeAsString(const clang::QualType &type) { std::stringstream stream; std::string name = type.getAsString(); // If it is an anonymous structure, print all the fields recursively if (name.substr(0,11) == "struct (ano") { stream << "struct { "; clang::RecordDecl* struct_decl = type.getTypePtr()->getAsStructureType()->getDecl(); // Print the types of all the fields for (const auto* field : struct_decl->fields()) { std::string type = GetTypeAsString(field->getType().getCanonicalType()); std::string name = field->getName(); stream << type; stream << " " << name << "; "; } stream << "}"; } else if (type.getTypePtr()->isBooleanType()) { return "bool"; } else { stream << type.getAsString(); //just print the type } return stream.str(); }
// updates S.Ok; and, depending on Kind, possibly S.FnAccumulatorOk or S.FnOutConverterOk void RSExportReduce::checkPointeeConstQualified(StateOfAnalyzeTranslationUnit &S, FnIdent Kind, const llvm::StringRef &Name, const clang::ParmVarDecl *Param, bool ExpectedQualification) { const clang::QualType ParamQType = Param->getType(); slangAssert(ParamQType->isPointerType()); const clang::QualType PointeeQType = ParamQType->getPointeeType(); if (PointeeQType.isConstQualified() != ExpectedQualification) { S.RSC.ReportError(Param->getLocation(), "%0 parameter '%1' (type '%2') must%3 point to const-qualified type") << S.DiagnosticDescription(getKey(Kind), Name) << Param->getName() << ParamQType.getAsString() << (ExpectedQualification ? "" : " not"); notOk(S, Kind); } }
// GET VECTOR TYPE FROM STRING rapidjson::Value SuperastCPP::createVectorValue(const clang::QualType qualType) { assert(isSTLVectorType(qualType)); //rapidjson::Value vectorValue(rapidjson::kObjectType); //vectorValue.AddMember("id", currentId++, allocator); const std::string& typeName = qualType.getAsString(); std::size_t actPos = 0; bool finished = false; unsigned depth = 0; std::string innerMostType; while (!finished) { // find next vector or comma std::size_t vectorPos = typeName.find(VECTOR_TYPE, actPos); std::size_t commaPos = typeName.find(",", actPos); std::string type = "vector"; if (commaPos < vectorPos) { finished = true; innerMostType = typeName.substr(actPos, commaPos-actPos); auto it = VECTOR_TYPE_MAPPING.find(type); if (it != VECTOR_TYPE_MAPPING.end()) innerMostType = it->second; } else { actPos = vectorPos + VECTOR_TYPE.size(); ++depth; } } rapidjson::Value actTypeValue(rapidjson::kObjectType); addId(actTypeValue); actTypeValue.AddMember("name", rapidjson::Value().SetString(innerMostType.c_str(), innerMostType.size(), allocator), allocator); for (unsigned i = 0; i < depth; ++i) { rapidjson::Value aux(rapidjson::kObjectType); addId(aux); aux.AddMember("name", "vector", allocator); aux.AddMember("data-type", actTypeValue, allocator); actTypeValue = aux; } return actTypeValue; }
ASTDumper::ASTDumper (clang::QualType type) { m_dump = type.getAsString(); }
static void StreamValue(llvm::raw_ostream& o, const void* V, clang::QualType Ty, cling::Interpreter& Interp) { clang::ASTContext& C = Interp.getCI()->getASTContext(); if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) { switch (BT->getKind()) { case clang::BuiltinType::Bool: if (*(const bool*)V) o << "true"; else o << "false"; break; case clang::BuiltinType::Char_U: // intentional fall through case clang::BuiltinType::UChar: // intentional fall through case clang::BuiltinType::Char_S: // intentional fall through case clang::BuiltinType::SChar: StreamChar(o, *(const char*)V); break; case clang::BuiltinType::Short: o << *(const short*)V; break; case clang::BuiltinType::UShort: o << *(const unsigned short*)V; break; case clang::BuiltinType::Int: o << *(const int*)V; break; case clang::BuiltinType::UInt: o << *(const unsigned int*)V; break; case clang::BuiltinType::Long: o << *(const long*)V; break; case clang::BuiltinType::ULong: o << *(const unsigned long*)V; break; case clang::BuiltinType::LongLong: o << *(const long long*)V; break; case clang::BuiltinType::ULongLong: o << *(const unsigned long long*)V; break; case clang::BuiltinType::Float: o << *(const float*)V; break; case clang::BuiltinType::Double: o << *(const double*)V; break; case clang::BuiltinType::LongDouble: { std::stringstream ssLD; ssLD << *(const long double*)V; o << ssLD.str() << 'L'; break; } default: StreamObj(o, V, Ty); } } else if (Ty.getAsString().compare("std::string") == 0) { StreamObj(o, V, Ty); o << " "; // force a space o <<"c_str: "; StreamCharPtr(o, ((const char*) (*(const std::string*)V).c_str())); } else if (Ty->isEnumeralType()) { clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl(); uint64_t value = *(const uint64_t*)V; bool IsFirst = true; llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty); for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; ++I) { if (I->getInitVal() == ValAsAPSInt) { if (!IsFirst) { o << " ? "; } o << "(" << I->getQualifiedNameAsString() << ")"; IsFirst = false; } } o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10); } else if (Ty->isReferenceType()) StreamRef(o, (const void**)&V, Ty, Interp); else if (Ty->isPointerType()) { clang::QualType PointeeTy = Ty->getPointeeType(); if (PointeeTy->isCharType()) StreamCharPtr(o, (const char*)V); else if (PointeeTy->isFunctionProtoType()) StreamFunction(o, V, PointeeTy, Interp); else StreamPtr(o, V); } else if (Ty->isArrayType()) StreamArr(o, V, Ty, Interp); else if (Ty->isFunctionType()) StreamFunction(o, V, Ty, Interp); else StreamObj(o, V, Ty); }
// Process "bool haltername(const compType *accum)" void RSExportReduce::analyzeHalter(StateOfAnalyzeTranslationUnit &S) { if (!S.FnHalter) // halter is always optional return; // Must return bool const clang::QualType ReturnTy = S.FnHalter->getReturnType().getCanonicalType(); if (!ReturnTy->isBooleanType()) { S.RSC.ReportError(S.FnHalter->getLocation(), "%0 must return bool not '%1'") << S.DiagnosticDescription(KeyHalter, mNameHalter) << ReturnTy.getAsString(); S.Ok = false; } // Must have exactly one parameter if (S.FnHalter->getNumParams() != 1) { S.RSC.ReportError(S.FnHalter->getLocation(), "%0 must take exactly 1 parameter (found %1)") << S.DiagnosticDescription(KeyHalter, mNameHalter) << S.FnHalter->getNumParams(); S.Ok = false; return; } // Parameter must not be a special parameter const clang::ParmVarDecl *const FnHalterParam = S.FnHalter->getParamDecl(0); if (isSpecialKernelParameter(FnHalterParam->getName())) { S.RSC.ReportError(S.FnHalter->getLocation(), "%0 cannot take special parameter '%1'") << S.DiagnosticDescription(KeyHalter, mNameHalter) << FnHalterParam->getName(); S.Ok = false; return; } // Parameter must be same type as first accumulator parameter if (S.FnAccumulatorParamFirstTy.isNull() || !S.FnAccumulatorParamFirstTy->isPointerType()) { // We're already in an error situation. We could compare against // the initializer parameter type or the first combiner parameter // type instead of the first accumulator parameter type (we'd have // to check for the availability of a parameter type there, too), // but it does not seem worth the effort. slangAssert(!S.Ok); return; } const clang::QualType FnHalterParamTy = FnHalterParam->getType().getCanonicalType(); if (!FnHalterParamTy->isPointerType() || !S.FnHalter->getASTContext().hasSameUnqualifiedType( S.FnAccumulatorParamFirstTy->getPointeeType().getCanonicalType(), FnHalterParamTy->getPointeeType().getCanonicalType())) { // <halter> parameter '<baz>' (type '<tbaz>') // and accumulator <goo>() parameter '<gaz>' (type '<tgaz>') must be pointers to the same type S.RSC.ReportError(S.FnHalter->getLocation(), "%0 parameter '%1' (type '%2') and %3 %4() parameter '%5' (type '%6')" " must be pointers to the same type") << S.DiagnosticDescription(KeyHalter, mNameHalter) << FnHalterParam->getName() << FnHalterParamTy.getAsString() << KeyAccumulator << mNameAccumulator << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString(); S.Ok = false; return; } // Parameter must point to const-qualified checkPointeeConstQualified(S, FN_IDENT_HALTER, mNameHalter, FnHalterParam, true); }
// Process "void outconvertname(resultType *result, const compType *accum)" void RSExportReduce::analyzeOutConverter(StateOfAnalyzeTranslationUnit &S) { if (!S.FnOutConverter) // outconverter is always optional return; // Must return void checkVoidReturn(S, FN_IDENT_OUT_CONVERTER, S.FnOutConverter); // Must have exactly two parameters if (S.FnOutConverter->getNumParams() != 2) { S.RSC.ReportError(S.FnOutConverter->getLocation(), "%0 must take exactly 2 parameters (found %1)") << S.DiagnosticDescription(KeyOutConverter, mNameOutConverter) << S.FnOutConverter->getNumParams(); S.Ok = S.FnOutConverterOk = false; return; } // Parameters must not be special and must be of pointer type; // and second parameter must match first accumulator parameter for (int ParamIdx = 0; ParamIdx < 2; ++ParamIdx) { clang::ParmVarDecl *const FnOutConverterParam = S.FnOutConverter->getParamDecl(ParamIdx); if (isSpecialKernelParameter(FnOutConverterParam->getName())) { S.RSC.ReportError(S.FnOutConverter->getLocation(), "%0 cannot take special parameter '%1'") << S.DiagnosticDescription(KeyOutConverter, mNameOutConverter) << FnOutConverterParam->getName(); S.Ok = S.FnOutConverterOk = false; continue; } const clang::QualType FnOutConverterParamTy = FnOutConverterParam->getType().getCanonicalType(); if (!FnOutConverterParamTy->isPointerType()) { S.RSC.ReportError(S.FnOutConverter->getLocation(), "%0 parameter '%1' must be of pointer type not '%2'") << S.DiagnosticDescription(KeyOutConverter, mNameOutConverter) << FnOutConverterParam->getName() << FnOutConverterParamTy.getAsString(); S.Ok = S.FnOutConverterOk = false; continue; } // Check const-qualification checkPointeeConstQualified(S, FN_IDENT_OUT_CONVERTER, mNameOutConverter, FnOutConverterParam, ParamIdx==1); if (ParamIdx == 0) { S.FnOutConverterParamFirst = FnOutConverterParam; S.FnOutConverterParamFirstTy = FnOutConverterParamTy; continue; } if (S.FnAccumulatorParamFirstTy.isNull() || !S.FnAccumulatorParamFirstTy->isPointerType()) { // We're already in an error situation. We could compare // against the initializer parameter type instead of the first // accumulator parameter type (we'd have to check for the // availability of a parameter type there, too), but it does not // seem worth the effort. slangAssert(!S.Ok); continue; } if (!S.FnOutConverter->getASTContext().hasSameUnqualifiedType( S.FnAccumulatorParamFirstTy->getPointeeType().getCanonicalType(), FnOutConverterParamTy->getPointeeType().getCanonicalType())) { // <outconverter> parameter '<baz>' (type '<tbaz>') // and accumulator <goo>() parameter '<gaz>' (type '<tgaz>') must be pointers to the same type S.RSC.ReportError(S.FnOutConverter->getLocation(), "%0 parameter '%1' (type '%2') and %3 %4() parameter '%5' (type '%6')" " must be pointers to the same type") << S.DiagnosticDescription(KeyOutConverter, mNameOutConverter) << FnOutConverterParam->getName() << FnOutConverterParamTy.getAsString() << KeyAccumulator << mNameAccumulator << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString(); S.Ok = S.FnOutConverterOk = false; } } }
// Process "void combinename(compType *accum, const compType *val)" void RSExportReduce::analyzeCombiner(StateOfAnalyzeTranslationUnit &S) { if (S.FnCombiner) { // Must return void checkVoidReturn(S, FN_IDENT_COMBINER, S.FnCombiner); // Must have exactly two parameters, of same type as first accumulator parameter if (S.FnCombiner->getNumParams() != 2) { S.RSC.ReportError(S.FnCombiner->getLocation(), "%0 must take exactly 2 parameters (found %1)") << S.DiagnosticDescription(KeyCombiner, mNameCombiner) << S.FnCombiner->getNumParams(); S.Ok = false; return; } if (S.FnAccumulatorParamFirstTy.isNull() || !S.FnAccumulatorParamFirstTy->isPointerType()) { // We're already in an error situation. We could compare // against the initializer parameter type instead of the first // accumulator parameter type (we'd have to check for the // availability of a parameter type there, too), but it does not // seem worth the effort. // // Likewise, we could compare the two combiner parameter types // against each other. slangAssert(!S.Ok); return; } for (int ParamIdx = 0; ParamIdx < 2; ++ParamIdx) { const clang::ParmVarDecl *const FnCombinerParam = S.FnCombiner->getParamDecl(ParamIdx); const clang::QualType FnCombinerParamTy = FnCombinerParam->getType().getCanonicalType(); if (!FnCombinerParamTy->isPointerType() || !S.FnCombiner->getASTContext().hasSameUnqualifiedType( S.FnAccumulatorParamFirstTy->getPointeeType().getCanonicalType(), FnCombinerParamTy->getPointeeType().getCanonicalType())) { // <combiner> parameter '<baz>' (type '<tbaz>') // and accumulator <goo>() parameter '<gaz>' (type '<tgaz>') must be pointers to the same type S.RSC.ReportError(S.FnCombiner->getLocation(), "%0 parameter '%1' (type '%2') and %3 %4() parameter '%5' (type '%6')" " must be pointers to the same type") << S.DiagnosticDescription(KeyCombiner, mNameCombiner) << FnCombinerParam->getName() << FnCombinerParamTy.getAsString() << KeyAccumulator << mNameAccumulator << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString(); S.Ok = false; } else { // Check const-qualification checkPointeeConstQualified(S, FN_IDENT_COMBINER, mNameCombiner, FnCombinerParam, ParamIdx==1); } } return; } // Ensure accumulator properties permit omission of combiner. if (!S.FnAccumulatorOk) { // Couldn't fully analyze accumulator, so cannot see whether it permits omission of combiner. return; } if (mAccumulatorIns.size() != 1 || S.FnAccumulatorIndexOfFirstSpecialParameter != S.FnAccumulator->getNumParams()) { S.RSC.ReportError(S.FnAccumulator->getLocation(), "%0 must have exactly 1 input" " and no special parameters in order for the %1 to be omitted") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << KeyCombiner; S.Ok = false; return; } const clang::ParmVarDecl *const FnAccumulatorParamInput = S.FnAccumulator->getParamDecl(1); const clang::QualType FnAccumulatorParamInputTy = FnAccumulatorParamInput->getType().getCanonicalType(); if (!S.FnAccumulator->getASTContext().hasSameUnqualifiedType( S.FnAccumulatorParamFirstTy->getPointeeType().getCanonicalType(), FnAccumulatorParamInputTy.getCanonicalType())) { S.RSC.ReportError(S.FnAccumulator->getLocation(), "%0 parameter '%1' (type '%2')" " must be pointer to the type of parameter '%3' (type '%4')" " in order for the %5 to be omitted") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString() << FnAccumulatorParamInput->getName() << FnAccumulatorParamInputTy.getAsString() << KeyCombiner; S.Ok = false; } }
// Process "void mNameAccumulator(compType *accum, in1Type in1, …, inNType inN[, specialarguments])" void RSExportReduce::analyzeAccumulator(StateOfAnalyzeTranslationUnit &S) { slangAssert(S.FnAccumulator); // Must return void checkVoidReturn(S, FN_IDENT_ACCUMULATOR, S.FnAccumulator); // Must have initial parameter of same type as initializer parameter // (if there is an initializer), followed by at least 1 input if (S.FnAccumulator->getNumParams() < 2) { S.RSC.ReportError(S.FnAccumulator->getLocation(), "%0 must take at least 2 parameters") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator); S.Ok = S.FnAccumulatorOk = false; return; } S.FnAccumulatorParamFirst = S.FnAccumulator->getParamDecl(0); S.FnAccumulatorParamFirstTy = S.FnAccumulatorParamFirst->getType().getCanonicalType(); // First parameter must be of pointer type if (!S.FnAccumulatorParamFirstTy->isPointerType()) { S.RSC.ReportError(S.FnAccumulator->getLocation(), "%0 parameter '%1' must be of pointer type not '%2'") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString(); S.Ok = S.FnAccumulatorOk = false; return; } // If there is an initializer with a pointer-typed parameter (as // opposed to an initializer with a bad parameter list), then // accumulator first parameter must be of same type as initializer // parameter if (S.FnInitializer && !S.FnInitializerParamTy.isNull() && S.FnInitializerParamTy->isPointerType() && !S.FnAccumulator->getASTContext().hasSameUnqualifiedType( S.FnInitializerParamTy->getPointeeType().getCanonicalType(), S.FnAccumulatorParamFirstTy->getPointeeType().getCanonicalType())) { // <accumulator> parameter '<baz>' (type '<tbaz>') and initializer <goo>() parameter '<gaz>' (type '<tgaz>') // must be pointers to the same type S.RSC.ReportError(S.FnAccumulator->getLocation(), "%0 parameter '%1' (type '%2') and %3 %4() parameter '%5' (type '%6')" " must be pointers to the same type") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString() << KeyInitializer << mNameInitializer << S.FnInitializerParam->getName() << S.FnInitializerParamTy.getAsString(); S.Ok = S.FnAccumulatorOk = false; } if (S.FnAccumulatorOk && S.FnAccumulatorParamFirstTy->getPointeeType()->isFunctionType()) { S.RSC.ReportError(S.FnAccumulator->getLocation(), "%0 parameter '%1' (type '%2') must not be pointer to function type") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString(); S.Ok = S.FnAccumulatorOk = false; } if (S.FnAccumulatorOk && S.FnAccumulatorParamFirstTy->getPointeeType()->isIncompleteType()) { S.RSC.ReportError(S.FnAccumulator->getLocation(), "%0 parameter '%1' (type '%2') must not be pointer to incomplete type") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString(); S.Ok = S.FnAccumulatorOk = false; } if (S.FnAccumulatorOk && HasRSObjectType(S.FnAccumulatorParamFirstTy->getPointeeType().getCanonicalType().getTypePtr())) { S.RSC.ReportError(S.FnAccumulator->getLocation(), "%0 parameter '%1' (type '%2') must not be pointer to data containing an object type") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString(); S.Ok = S.FnAccumulatorOk = false; } // Parameter must not point to const-qualified checkPointeeConstQualified(S, FN_IDENT_ACCUMULATOR, mNameAccumulator, S.FnAccumulatorParamFirst, false); // Analyze special parameters S.Ok &= (S.FnAccumulatorOk &= processSpecialKernelParameters( &S.RSC, std::bind(S.DiagnosticDescription, KeyAccumulator, mNameAccumulator), S.FnAccumulator, &S.FnAccumulatorIndexOfFirstSpecialParameter, &mAccumulatorSignatureMetadata)); // Must have at least an accumulator and an input. // If we get here we know there are at least 2 arguments; so the only problem case is // where we have an accumulator followed immediately by a special parameter. if (S.FnAccumulatorIndexOfFirstSpecialParameter < 2) { slangAssert(S.FnAccumulatorIndexOfFirstSpecialParameter < S.FnAccumulator->getNumParams()); S.RSC.ReportError(S.FnAccumulator->getLocation(), "%0 must have at least 1 input ('%1' is a special parameter)") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << S.FnAccumulator->getParamDecl(S.FnAccumulatorIndexOfFirstSpecialParameter)->getName(); S.Ok = S.FnAccumulatorOk = false; return; } if (S.FnAccumulatorOk) { mAccumulatorSignatureMetadata |= bcinfo::MD_SIG_In; mAccumulatorTypeSize = S.ASTC.getTypeSizeInChars(S.FnAccumulatorParamFirstTy->getPointeeType()).getQuantity(); for (size_t ParamIdx = 1; ParamIdx < S.FnAccumulatorIndexOfFirstSpecialParameter; ++ParamIdx) { const clang::ParmVarDecl *const Param = S.FnAccumulator->getParamDecl(ParamIdx); mAccumulatorIns.push_back(Param); const clang::QualType ParamQType = Param->getType().getCanonicalType(); const clang::Type *ParamType = ParamQType.getTypePtr(); RSExportType *ParamEType = nullptr; if (ParamQType->isPointerType()) { S.RSC.ReportError(Param->getLocation(), "%0 parameter '%1' (type '%2') must not be a pointer") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << Param->getName() << ParamQType.getAsString(); S.Ok = false; } else if (HasRSObjectType(ParamType)) { S.RSC.ReportError(Param->getLocation(), "%0 parameter '%1' (type '%2') must not contain an object type") << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator) << Param->getName() << ParamQType.getAsString(); S.Ok = false; } else if (RSExportType::ValidateType(&S.RSC, S.ASTC, ParamQType, Param, Param->getLocStart(), S.RSC.getTargetAPI(), false /* IsFilterscript */, true /* IsExtern */)) { // TODO: Better diagnostics on validation or creation failure? ParamEType = RSExportType::Create(&S.RSC, ParamType, NotLegacyKernelArgument); S.Ok &= (ParamEType != nullptr); } else { S.Ok = false; } mAccumulatorInTypes.push_back(ParamEType); // possibly nullptr } } }
// IF IT IS A VECTOR TYPE bool SuperastCPP::isSTLVectorType(const clang::QualType qualType) { const std::string& typeName = qualType.getAsString(); return typeName.find(VECTOR_TYPE) != std::string::npos; }
std::string CASTHelper::getTypeRef(clang::QualType type) { return type.getAsString(*m_langOption); };