10 #include "clang/Lex/Lexer.h"
11 #include "clang/Tooling/FixIt.h"
12 #include "llvm/ADT/StringSet.h"
31 auto ItPair = MultiMap.equal_range(
Kind);
32 while (ItPair.first != ItPair.second) {
33 if (ItPair.first->second == MPIDatatype)
46 static llvm::StringSet<> AllTypes = {
"MPI_C_BOOL",
59 "MPI_UNSIGNED_LONG_LONG",
64 "MPI_C_FLOAT_COMPLEX",
65 "MPI_C_DOUBLE_COMPLEX",
66 "MPI_C_LONG_DOUBLE_COMPLEX",
76 "MPI_CXX_FLOAT_COMPLEX",
77 "MPI_CXX_DOUBLE_COMPLEX",
78 "MPI_CXX_LONG_DOUBLE_COMPLEX"};
80 return AllTypes.find(MPIDatatype) != AllTypes.end();
92 std::string &BufferTypeName,
93 StringRef MPIDatatype,
94 const LangOptions &LO) {
95 static std::multimap<BuiltinType::Kind, StringRef> BuiltinMatches = {
98 {BuiltinType::SChar,
"MPI_CHAR"},
99 {BuiltinType::SChar,
"MPI_SIGNED_CHAR"},
100 {BuiltinType::SChar,
"MPI_UNSIGNED_CHAR"},
101 {BuiltinType::Char_S,
"MPI_CHAR"},
102 {BuiltinType::Char_S,
"MPI_SIGNED_CHAR"},
103 {BuiltinType::Char_S,
"MPI_UNSIGNED_CHAR"},
104 {BuiltinType::UChar,
"MPI_CHAR"},
105 {BuiltinType::UChar,
"MPI_SIGNED_CHAR"},
106 {BuiltinType::UChar,
"MPI_UNSIGNED_CHAR"},
107 {BuiltinType::Char_U,
"MPI_CHAR"},
108 {BuiltinType::Char_U,
"MPI_SIGNED_CHAR"},
109 {BuiltinType::Char_U,
"MPI_UNSIGNED_CHAR"},
110 {BuiltinType::WChar_S,
"MPI_WCHAR"},
111 {BuiltinType::WChar_U,
"MPI_WCHAR"},
112 {BuiltinType::Bool,
"MPI_C_BOOL"},
113 {BuiltinType::Bool,
"MPI_CXX_BOOL"},
114 {BuiltinType::Short,
"MPI_SHORT"},
115 {BuiltinType::Int,
"MPI_INT"},
116 {BuiltinType::Long,
"MPI_LONG"},
117 {BuiltinType::LongLong,
"MPI_LONG_LONG"},
118 {BuiltinType::LongLong,
"MPI_LONG_LONG_INT"},
119 {BuiltinType::UShort,
"MPI_UNSIGNED_SHORT"},
120 {BuiltinType::UInt,
"MPI_UNSIGNED"},
121 {BuiltinType::ULong,
"MPI_UNSIGNED_LONG"},
122 {BuiltinType::ULongLong,
"MPI_UNSIGNED_LONG_LONG"},
123 {BuiltinType::Float,
"MPI_FLOAT"},
124 {BuiltinType::Double,
"MPI_DOUBLE"},
125 {BuiltinType::LongDouble,
"MPI_LONG_DOUBLE"}};
128 BufferTypeName = std::string(Builtin->getName(LO));
145 std::string &BufferTypeName,
146 StringRef MPIDatatype,
147 const LangOptions &LO) {
148 static std::multimap<BuiltinType::Kind, StringRef> ComplexCMatches = {
149 {BuiltinType::Float,
"MPI_C_COMPLEX"},
150 {BuiltinType::Float,
"MPI_C_FLOAT_COMPLEX"},
151 {BuiltinType::Double,
"MPI_C_DOUBLE_COMPLEX"},
152 {BuiltinType::LongDouble,
"MPI_C_LONG_DOUBLE_COMPLEX"}};
154 const auto *Builtin =
155 Complex->getElementType().getTypePtr()->getAs<BuiltinType>();
159 BufferTypeName = (llvm::Twine(Builtin->getName(LO)) +
" _Complex").str();
176 std::string &BufferTypeName, StringRef MPIDatatype,
177 const LangOptions &LO) {
178 static std::multimap<BuiltinType::Kind, StringRef> ComplexCXXMatches = {
179 {BuiltinType::Float,
"MPI_CXX_FLOAT_COMPLEX"},
180 {BuiltinType::Double,
"MPI_CXX_DOUBLE_COMPLEX"},
181 {BuiltinType::LongDouble,
"MPI_CXX_LONG_DOUBLE_COMPLEX"}};
183 if (Template->getAsCXXRecordDecl()->getName() !=
"complex")
186 const auto *Builtin =
187 Template->getArg(0).getAsType().getTypePtr()->getAs<BuiltinType>();
192 (llvm::Twine(
"complex<") + Builtin->getName(LO) +
">").str();
207 std::string &BufferTypeName,
208 StringRef MPIDatatype) {
209 static llvm::StringMap<StringRef> FixedWidthMatches = {
210 {
"int8_t",
"MPI_INT8_T"}, {
"int16_t",
"MPI_INT16_T"},
211 {
"int32_t",
"MPI_INT32_T"}, {
"int64_t",
"MPI_INT64_T"},
212 {
"uint8_t",
"MPI_UINT8_T"}, {
"uint16_t",
"MPI_UINT16_T"},
213 {
"uint32_t",
"MPI_UINT32_T"}, {
"uint64_t",
"MPI_UINT64_T"}};
215 const auto It = FixedWidthMatches.find(Typedef->getDecl()->getName());
217 if (It != FixedWidthMatches.end() && It->getValue() != MPIDatatype) {
218 BufferTypeName = std::string(Typedef->getDecl()->getName());
231 const QualType QT =
CE->getArg(Idx)->IgnoreImpCasts()->getType();
232 return QT.getTypePtr()->getPointeeOrArrayElementType();
235 void TypeMismatchCheck::registerMatchers(MatchFinder *Finder) {
236 Finder->addMatcher(callExpr().bind(
"CE"),
this);
240 const auto *
const CE = Result.Nodes.getNodeAs<CallExpr>(
"CE");
241 if (!
CE->getDirectCallee())
245 FuncClassifier.emplace(*Result.Context);
247 const IdentifierInfo *Identifier =
CE->getDirectCallee()->getIdentifier();
248 if (!Identifier || !FuncClassifier->isMPIType(Identifier))
252 SmallVector<const Type *, 1> BufferTypes;
253 SmallVector<const Expr *, 1> BufferExprs;
254 SmallVector<StringRef, 1> MPIDatatypes;
258 auto AddPair = [&
CE, &Result, &BufferTypes, &BufferExprs, &MPIDatatypes](
259 const size_t BufferIdx,
const size_t DatatypeIdx) {
261 if (
CE->getArg(BufferIdx)->isNullPointerConstant(
262 *Result.Context, Expr::NPC_ValueDependentIsNull) ||
267 StringRef MPIDatatype =
275 BufferTypes.push_back(ArgType);
276 BufferExprs.push_back(
CE->getArg(BufferIdx));
277 MPIDatatypes.push_back(MPIDatatype);
281 if (FuncClassifier->isPointToPointType(Identifier)) {
283 }
else if (FuncClassifier->isCollectiveType(Identifier)) {
284 if (FuncClassifier->isReduceType(Identifier)) {
287 }
else if (FuncClassifier->isScatterType(Identifier) ||
288 FuncClassifier->isGatherType(Identifier) ||
289 FuncClassifier->isAlltoallType(Identifier)) {
292 }
else if (FuncClassifier->isBcastType(Identifier)) {
296 checkArguments(BufferTypes, BufferExprs, MPIDatatypes, getLangOpts());
299 void TypeMismatchCheck::checkArguments(ArrayRef<const Type *> BufferTypes,
300 ArrayRef<const Expr *> BufferExprs,
301 ArrayRef<StringRef> MPIDatatypes,
302 const LangOptions &LO) {
303 std::string BufferTypeName;
305 for (
size_t I = 0; I < MPIDatatypes.size(); ++I) {
306 const Type *
const BT = BufferTypes[I];
309 if (
const auto *Typedef = BT->getAs<TypedefType>()) {
311 }
else if (
const auto *Complex = BT->getAs<ComplexType>()) {
314 }
else if (
const auto *Template = BT->getAs<TemplateSpecializationType>()) {
316 MPIDatatypes[I], LO);
317 }
else if (
const auto *Builtin = BT->getAs<BuiltinType>()) {
323 const auto Loc = BufferExprs[I]->getSourceRange().getBegin();
324 diag(
Loc,
"buffer type '%0' does not match the MPI datatype '%1'")
325 << BufferTypeName << MPIDatatypes[I];
330 void TypeMismatchCheck::onEndOfTranslationUnit() { FuncClassifier.reset(); }