Skip to content

Commit ade6a17

Browse files
committed
[nomp] Fix parsing errors in nomp_init()
1 parent 96af364 commit ade6a17

File tree

2 files changed

+92
-14
lines changed

2 files changed

+92
-14
lines changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1528,7 +1528,7 @@ def err_nomp_eod_expected: Error<
15281528
def err_nomp_identifier_expected: Error<
15291529
"Expected a variable name at line %0, column %1">;
15301530
def err_nomp_function_arg_invalid: Error<
1531-
"Invalid argument type at line %0, column %1">;
1531+
"Invalid argument type at line %0, column %1: %2">;
15321532
def err_nomp_pointer_type_expected: Error<
15331533
"Expected a pointer in the nomp directive '%0' at line %1, column %2">;
15341534
def err_nomp_for_expected: Error<

clang/lib/Parse/ParseNomp.cpp

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ static inline void NompHandleError(unsigned DiagID, SourceLocation SL,
155155
<< loc.getLineNumber() << loc.getColumnNumber();
156156
else
157157
AST.getDiagnostics().Report(loc, DiagID)
158-
<< Arg << loc.getLineNumber() << loc.getColumnNumber();
158+
<< loc.getLineNumber() << loc.getColumnNumber() << Arg;
159159
}
160160

161161
//==============================================================================
@@ -240,17 +240,97 @@ void Parser::ParseNompExprListUntilRParen(llvm::SmallVector<Expr *, 16> &EL,
240240
NompHandleError(diag::err_nomp_rparen_expected, Tok, *this, Pragma);
241241
}
242242

243-
static Expr *ExprToICE(Expr *E, const ASTContext &AST, QualType QT,
244-
CastKind CK) {
245-
if (IntegerLiteral *IL = dyn_cast_or_null<IntegerLiteral>(E)) {
246-
// FIXME: If it is a Literal, use as is. Need to add checks for
247-
// StringLiteral, FloatLiteral, etc.
248-
return IL;
243+
static Expr *ExprToArgc(Expr *E, ASTContext &AST) {
244+
const Type *T = E->getType().getTypePtr();
245+
if (!T->isIntegerType() && !T->isFloatingType()) {
246+
NompHandleError(diag::err_nomp_function_arg_invalid, E->getExprLoc(), AST,
247+
"Parameter `argc` of nomp_init() must be an Integer type.");
248+
return nullptr;
249+
}
250+
251+
QualType QT = getIntType(AST);
252+
Expr *Argc = nullptr;
253+
254+
// If this is a DRE, we need to do LValueToRvalue cast. Otherwise, we just
255+
// set the Argc to E.
256+
if (DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
257+
Argc = ImplicitCastExpr::Create(
258+
AST, DRE->getType(), CastKind::CK_LValueToRValue, DRE, nullptr,
259+
ExprValueKind::VK_PRValue, FPOptionsOverride());
249260
} else {
250-
// If it is a Expr, do an ICE.
251-
return ImplicitCastExpr::Create(AST, QT, CK, E, nullptr, VK_PRValue,
261+
Argc = E;
262+
}
263+
264+
// If this is a floating type, we need to do FloatingToIntegral cast.
265+
if (T->isFloatingType()) {
266+
Argc = ImplicitCastExpr::Create(AST, QT, CastKind::CK_FloatingToIntegral,
267+
Argc, nullptr, ExprValueKind::VK_PRValue,
268+
FPOptionsOverride());
269+
}
270+
271+
return Argc;
272+
}
273+
274+
static Expr *ExprToArgv(Expr *E, ASTContext &AST) {
275+
#define check_cond(cond) \
276+
{ \
277+
if (!cond) { \
278+
NompHandleError(diag::err_nomp_function_arg_invalid, E->getExprLoc(), \
279+
AST, \
280+
"Parameter `argv` of nomp_init() must be an variable " \
281+
"which reference an array of C-strings or " \
282+
"pointer to an array of C-strings."); \
283+
return nullptr; \
284+
} \
285+
}
286+
287+
// We should have a variable pointing to array of C-strings or a pointer to
288+
// an array of C-strings as the argv.
289+
290+
// So, we first check if this is a DeclRefExpr since we are only accepting
291+
// variables to pointer or array types.
292+
bool isa_variable = false;
293+
if (DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
294+
// If this is a DeclRefExpr, we need to check if it is a variable.
295+
if (isa<VarDecl>(DRE->getDecl()))
296+
isa_variable = true;
297+
}
298+
check_cond(isa_variable);
299+
300+
// Then, check if it is a variable of an array or a pointer type.
301+
bool isa_array_or_pointer = false;
302+
const Type *T = E->getType().getTypePtr();
303+
if (T->isPointerType() || T->isArrayType())
304+
isa_array_or_pointer = true;
305+
check_cond(isa_array_or_pointer);
306+
307+
// If it is an array or a pointer, then we check if the base type is a
308+
// C-string.
309+
bool isa_cstring = false;
310+
const Type *B = T->getPointeeOrArrayElementType();
311+
if (B->isPointerType() && B->getPointeeType()->isCharType())
312+
isa_cstring = true;
313+
check_cond(isa_cstring);
314+
315+
QualType QT = AST.getPointerType(AST.getConstType(AST.CharTy));
316+
QT = AST.getPointerType(QT);
317+
// If this is an array, we need to do ArrayToPointerDecay cast.
318+
if (T->isArrayType()) {
319+
return ImplicitCastExpr::Create(AST, QT, CastKind::CK_ArrayToPointerDecay,
320+
E, nullptr, ExprValueKind::VK_PRValue,
321+
FPOptionsOverride());
322+
}
323+
324+
// If this is a pointer type, we do an LValueToRValue cast.
325+
if (T->isPointerType()) {
326+
return ImplicitCastExpr::Create(AST, QT, CastKind::CK_LValueToRValue, E,
327+
nullptr, ExprValueKind::VK_PRValue,
252328
FPOptionsOverride());
253329
}
330+
331+
return nullptr;
332+
333+
#undef check_cond
254334
}
255335

256336
//==============================================================================
@@ -279,10 +359,8 @@ StmtResult Parser::ParseNompInit(const SourceLocation &SL) {
279359
// Conver Expr* to function arguments.
280360
llvm::SmallVector<Expr *, 2> FuncArgs;
281361
Expr *Argv = InitArgs.pop_back_val(), *Argc = InitArgs.pop_back_val();
282-
FuncArgs.push_back(
283-
ExprToICE(Argc, AST, getIntType(AST), CastKind::CK_LValueToRValue));
284-
FuncArgs.push_back(
285-
ExprToICE(Argv, AST, getIntType(AST), CastKind::CK_LValueToRValue));
362+
FuncArgs.push_back(ExprToArgc(Argc, AST));
363+
FuncArgs.push_back(ExprToArgv(Argv, AST));
286364

287365
ConsumeAnnotationToken(); // tok::annot_pragma_nomp_end
288366

0 commit comments

Comments
 (0)