Пример #1
0
/**
 * 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);
  }
}
Пример #3
0
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);
  }
}
Пример #5
0
// 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;
}
Пример #6
0
ASTDumper::ASTDumper (clang::QualType type)
{
    m_dump = type.getAsString();
}
Пример #7
0
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
    }
  }
}
Пример #12
0
// 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;
}
Пример #13
0
std::string CASTHelper::getTypeRef(clang::QualType type)
{
	return type.getAsString(*m_langOption);
};