Opts.AddVFSOverlayFile(A->getValue());
}
-static bool isOpenCL(LangStandard::Kind LangStd) {
- return LangStd == LangStandard::lang_opencl ||
- LangStd == LangStandard::lang_opencl11 ||
- LangStd == LangStandard::lang_opencl12 ||
- LangStd == LangStandard::lang_opencl20;
-}
-
void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
const llvm::Triple &T,
PreprocessorOptions &PPOpts,
Opts.ImplicitInt = Std.hasImplicitInt();
// Set OpenCL Version.
- Opts.OpenCL = isOpenCL(LangStd) || IK == IK_OpenCL;
+ Opts.OpenCL = Std.isOpenCL() || IK == IK_OpenCL;
if (LangStd == LangStandard::lang_opencl)
Opts.OpenCLVersion = 100;
else if (LangStd == LangStandard::lang_opencl11)
return DefaultVisibility;
}
+/// Check if input file kind and language standard are compatible.
+static bool IsInputCompatibleWithStandard(InputKind IK,
+ const LangStandard &S) {
+ switch (IK) {
+ case IK_C:
+ case IK_ObjC:
+ case IK_PreprocessedC:
+ case IK_PreprocessedObjC:
+ if (S.isC89() || S.isC99())
+ return true;
+ break;
+ case IK_CXX:
+ case IK_ObjCXX:
+ case IK_PreprocessedCXX:
+ case IK_PreprocessedObjCXX:
+ if (S.isCPlusPlus())
+ return true;
+ break;
+ case IK_OpenCL:
+ if (S.isOpenCL())
+ return true;
+ break;
+ case IK_CUDA:
+ case IK_PreprocessedCuda:
+ if (S.isCPlusPlus())
+ return true;
+ break;
+ default:
+ llvm_unreachable("Cannot decide whether language standard and "
+ "input file kind are compatible!");
+ }
+ return false;
+}
+
+/// Get language name for given input kind.
+static const StringRef GetInputKindName(InputKind IK) {
+ switch (IK) {
+ case IK_C:
+ case IK_ObjC:
+ case IK_PreprocessedC:
+ case IK_PreprocessedObjC:
+ return "C/ObjC";
+ case IK_CXX:
+ case IK_ObjCXX:
+ case IK_PreprocessedCXX:
+ case IK_PreprocessedObjCXX:
+ return "C++/ObjC++";
+ case IK_OpenCL:
+ return "OpenCL";
+ case IK_CUDA:
+ case IK_PreprocessedCuda:
+ return "CUDA";
+ default:
+ llvm_unreachable("Cannot decide on name for InputKind!");
+ }
+}
+
static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
const TargetOptions &TargetOpts,
PreprocessorOptions &PPOpts,
.Case(alias, LangStandard::lang_##id)
#include "clang/Frontend/LangStandards.def"
.Default(LangStandard::lang_unspecified);
- if (LangStd == LangStandard::lang_unspecified)
+ if (LangStd == LangStandard::lang_unspecified) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
- else {
+ // Report supported standards with short description.
+ for (unsigned KindValue = 0;
+ KindValue != LangStandard::lang_unspecified;
+ ++KindValue) {
+ const LangStandard &Std = LangStandard::getLangStandardForKind(
+ static_cast<LangStandard::Kind>(KindValue));
+ if (IsInputCompatibleWithStandard(IK, Std)) {
+ Diags.Report(diag::note_drv_use_standard)
+ << Std.getName() << Std.getDescription();
+ }
+ }
+ } else {
// Valid standard, check to make sure language and standard are
// compatible.
const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
- switch (IK) {
- case IK_C:
- case IK_ObjC:
- case IK_PreprocessedC:
- case IK_PreprocessedObjC:
- if (!(Std.isC89() || Std.isC99()))
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "C/ObjC";
- break;
- case IK_CXX:
- case IK_ObjCXX:
- case IK_PreprocessedCXX:
- case IK_PreprocessedObjCXX:
- if (!Std.isCPlusPlus())
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "C++/ObjC++";
- break;
- case IK_OpenCL:
- if (!isOpenCL(LangStd))
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "OpenCL";
- break;
- case IK_CUDA:
- case IK_PreprocessedCuda:
- if (!Std.isCPlusPlus())
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "CUDA";
- break;
- default:
- break;
+ if (!IsInputCompatibleWithStandard(IK, Std)) {
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << GetInputKindName(IK);
}
}
}
// Override the -std option in this case.
if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
LangStandard::Kind OpenCLLangStd
- = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
- .Cases("cl", "CL", LangStandard::lang_opencl)
- .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11)
- .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12)
- .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20)
- .Default(LangStandard::lang_unspecified);
+ = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
+ .Cases("cl", "CL", LangStandard::lang_opencl)
+ .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11)
+ .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12)
+ .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20)
+ .Default(LangStandard::lang_unspecified);
if (OpenCLLangStd == LangStandard::lang_unspecified) {
Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue();
+ << A->getAsString(Args) << A->getValue();
}
else
LangStd = OpenCLLangStd;
if (Args.hasArg(OPT_fgnu89_inline)) {
if (Opts.CPlusPlus)
- Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fgnu89-inline"
- << "C++/ObjC++";
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << "-fgnu89-inline" << GetInputKindName(IK);
else
Opts.GNUInline = 1;
}
--- /dev/null
+// This file checks output given when processing C/ObjC files.
+// When user selects invalid language standard
+// print out supported values with short description.
+
+// RUN: not %clang %s -std=foobar -c 2>&1 | \
+// RUN: FileCheck --match-full-lines %s
+
+// CHECK: error: invalid value 'foobar' in '-std=foobar'
+// CHECK-NEXT: note: use 'c89' for 'ISO C 1990' standard
+// CHECK-NEXT: note: use 'c90' for 'ISO C 1990' standard
+// CHECK-NEXT: note: use 'iso9899:1990' for 'ISO C 1990' standard
+// CHECK-NEXT: note: use 'iso9899:199409' for 'ISO C 1990 with amendment 1' standard
+// CHECK-NEXT: note: use 'gnu89' for 'ISO C 1990 with GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu90' for 'ISO C 1990 with GNU extensions' standard
+// CHECK-NEXT: note: use 'c99' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'c9x' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'iso9899:1999' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'iso9899:199x' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'gnu99' for 'ISO C 1999 with GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu9x' for 'ISO C 1999 with GNU extensions' standard
+// CHECK-NEXT: note: use 'c11' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'c1x' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'iso9899:2011' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'iso9899:201x' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'gnu11' for 'ISO C 2011 with GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu1x' for 'ISO C 2011 with GNU extensions' standard
+// CHECK-NEXT: note: use 'cl' for 'OpenCL 1.0' standard
+// CHECK-NEXT: note: use 'cl1.1' for 'OpenCL 1.1' standard
+// CHECK-NEXT: note: use 'cl1.2' for 'OpenCL 1.2' standard
+// CHECK-NEXT: note: use 'cl2.0' for 'OpenCL 2.0' standard
+
+// Make sure that no other output is present.
+// CHECK-NOT: {{^.+$}}
+
--- /dev/null
+// This file checks output given when processing C++/ObjC++ files.
+// When user selects invalid language standard
+// print out supported values with short description.
+
+// RUN: not %clang %s -std=foobar -c 2>&1 | \
+// RUN: FileCheck --match-full-lines %s
+
+// CHECK: error: invalid value 'foobar' in '-std=foobar'
+// CHECK-NEXT: note: use 'c++98' for 'ISO C++ 1998 with amendments' standard
+// CHECK-NEXT: note: use 'c++03' for 'ISO C++ 1998 with amendments' standard
+// CHECK-NEXT: note: use 'gnu++98' for 'ISO C++ 1998 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'c++0x' for 'ISO C++ 2011 with amendments' standard
+// CHECK-NEXT: note: use 'c++11' for 'ISO C++ 2011 with amendments' standard
+// CHECK-NEXT: note: use 'gnu++0x' for 'ISO C++ 2011 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu++11' for 'ISO C++ 2011 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'c++1y' for 'ISO C++ 2014 with amendments' standard
+// CHECK-NEXT: note: use 'c++14' for 'ISO C++ 2014 with amendments' standard
+// CHECK-NEXT: note: use 'gnu++1y' for 'ISO C++ 2014 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu++14' for 'ISO C++ 2014 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'c++1z' for 'Working draft for ISO C++ 2017' standard
+// CHECK-NEXT: note: use 'gnu++1z' for 'Working draft for ISO C++ 2017 with GNU extensions' standard
+// CHECK-NEXT: note: use 'cuda' for 'NVIDIA CUDA(tm)' standard
+
+// Make sure that no other output is present.
+// CHECK-NOT: {{^.+$}}
+