Skip to content

Commit

Permalink
[Driver][AVR] Fix warn_drv_avr_stdlib_not_linked condition
Browse files Browse the repository at this point in the history
Many options (-fsyntax-only, -E, -S, etc) skip the link action phase which the
existing condition does not account for.

Since the code no longer specifies OPT_c, I think a single RUN line about -c
not leading to a warning is sufficient. Adding one for all of -E,
-fsyntax-only, -S would be excessive.

Reviewed By: benshi001

Differential Revision: https://reviews.llvm.org/D122553
  • Loading branch information
MaskRay committed Mar 28, 2022
1 parent c49af35 commit 52fa1d1
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 66 deletions.
80 changes: 42 additions & 38 deletions clang/lib/Driver/ToolChains/AVR.cpp
Expand Up @@ -366,49 +366,19 @@ const StringRef PossibleAVRLibcLocations[] = {
/// AVR Toolchain
AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args), LinkStdlib(false) {
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);

// Only add default libraries if the user hasn't explicitly opted out.
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs) &&
!Args.hasArg(options::OPT_c /* does not apply when not linking */)) {
std::string CPU = getCPUName(D, Args, Triple);

if (CPU.empty()) {
// We cannot link any standard libraries without an MCU specified.
D.Diag(diag::warn_drv_avr_mcu_not_specified);
!Args.hasArg(options::OPT_nodefaultlibs)) {
if (GCCInstallation.isValid()) {
GCCInstallPath = GCCInstallation.getInstallPath();
std::string GCCParentPath(GCCInstallation.getParentLibPath());
getProgramPaths().push_back(GCCParentPath + "/../bin");
} else {
Optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
Optional<std::string> AVRLibcRoot = findAVRLibcInstallation();

if (!FamilyName.hasValue()) {
// We do not have an entry for this CPU in the family
// mapping table yet.
D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
<< CPU;
} else if (!GCCInstallation.isValid()) {
// No avr-gcc found and so no runtime linked.
D.Diag(diag::warn_drv_avr_gcc_not_found);
} else if (!AVRLibcRoot.hasValue()) {
// No avr-libc found and so no runtime linked.
D.Diag(diag::warn_drv_avr_libc_not_found);
} else { // We have enough information to link stdlibs
std::string GCCRoot(GCCInstallation.getInstallPath());
std::string GCCParentPath(GCCInstallation.getParentLibPath());
std::string LibcRoot = AVRLibcRoot.getValue();
std::string SubPath = GetMCUSubPath(CPU);

getProgramPaths().push_back(GCCParentPath + "/../bin");
getFilePaths().push_back(LibcRoot + std::string("/lib/") + SubPath);
getFilePaths().push_back(GCCRoot + std::string("/") + SubPath);

LinkStdlib = true;
}
D.Diag(diag::warn_drv_avr_gcc_not_found);
}

if (!LinkStdlib)
D.Diag(diag::warn_drv_avr_stdlib_not_linked);
}
}

Expand Down Expand Up @@ -445,13 +415,14 @@ void AVRToolChain::addClangTargetOptions(
}

Tool *AVRToolChain::buildLinker() const {
return new tools::AVR::Linker(getTriple(), *this, LinkStdlib);
return new tools::AVR::Linker(getTriple(), *this);
}

void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs, const ArgList &Args,
const char *LinkingOutput) const {
const auto &TC = static_cast<const AVRToolChain &>(getToolChain());
const Driver &D = getToolChain().getDriver();

// Compute information about the target AVR.
Expand All @@ -473,6 +444,39 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
getToolChain().AddFilePathLibArgs(Args, CmdArgs);

// Only add default libraries if the user hasn't explicitly opted out.
bool LinkStdlib = false;
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
if (CPU.empty()) {
// We cannot link any standard libraries without an MCU specified.
D.Diag(diag::warn_drv_avr_mcu_not_specified);
} else {
Optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
Optional<std::string> AVRLibcRoot = TC.findAVRLibcInstallation();

if (!FamilyName) {
// We do not have an entry for this CPU in the family
// mapping table yet.
D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
<< CPU;
} else if (!AVRLibcRoot) {
// No avr-libc found and so no runtime linked.
D.Diag(diag::warn_drv_avr_libc_not_found);
} else if (!TC.getGCCInstallPath().empty()) {
std::string SubPath = GetMCUSubPath(CPU);
CmdArgs.push_back(
Args.MakeArgString(Twine("-L") + *AVRLibcRoot + "/lib/" + SubPath));
CmdArgs.push_back(
Args.MakeArgString("-L" + TC.getGCCInstallPath() + "/" + SubPath));
LinkStdlib = true;
}
}

if (!LinkStdlib)
D.Diag(diag::warn_drv_avr_stdlib_not_linked);
}

if (SectionAddressData.hasValue()) {
std::string DataSectionArg = std::string("-Tdata=0x") +
llvm::utohexstr(SectionAddressData.getValue());
Expand Down
17 changes: 6 additions & 11 deletions clang/lib/Driver/ToolChains/AVR.h
Expand Up @@ -31,17 +31,14 @@ class LLVM_LIBRARY_VISIBILITY AVRToolChain : public Generic_ELF {
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const override;

llvm::Optional<std::string> findAVRLibcInstallation() const;
StringRef getGCCInstallPath() const { return GCCInstallPath; }

protected:
Tool *buildLinker() const override;

private:
/// Whether libgcc, libct, and friends should be linked.
///
/// This is not done if the user does not specify a
/// microcontroller on the command line.
bool LinkStdlib;

llvm::Optional<std::string> findAVRLibcInstallation() const;
StringRef GCCInstallPath;
};

} // end namespace toolchains
Expand All @@ -50,9 +47,8 @@ namespace tools {
namespace AVR {
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
Linker(const llvm::Triple &Triple, const ToolChain &TC, bool LinkStdlib)
: Tool("AVR::Linker", "avr-ld", TC), Triple(Triple),
LinkStdlib(LinkStdlib) {}
Linker(const llvm::Triple &Triple, const ToolChain &TC)
: Tool("AVR::Linker", "avr-ld", TC), Triple(Triple) {}

bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
Expand All @@ -63,7 +59,6 @@ class LLVM_LIBRARY_VISIBILITY Linker : public Tool {

protected:
const llvm::Triple &Triple;
bool LinkStdlib;
};
} // end namespace AVR
} // end namespace tools
Expand Down
10 changes: 0 additions & 10 deletions clang/test/Driver/avr-link-no-mcu-specified.c

This file was deleted.

22 changes: 15 additions & 7 deletions clang/test/Driver/avr-toolchain.c
@@ -1,7 +1,7 @@
// UNSUPPORTED: system-windows
// A basic clang -cc1 command-line.

// RUN: %clang %s -### -target avr --sysroot %S/Inputs/basic_avr_tree -resource-dir=%S/Inputs/resource_dir 2>&1 | FileCheck --check-prefix=CHECK1 %s
// RUN: %clang %s -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -resource-dir=%S/Inputs/resource_dir 2>&1 | FileCheck --check-prefix=CHECK1 %s
// CHECK1: clang{{.*}} "-cc1" "-triple" "avr"
// CHECK1-SAME: "-resource-dir" "[[RESOURCE:[^"]+]]"
// CHECK1-SAME: "-isysroot" "[[SYSROOT:[^"]+/basic_avr_tree]]"
Expand All @@ -12,26 +12,34 @@
// CHECK1-SAME: "-o" "a.out"
// CHECK1-SAME: {{^}} "--gc-sections"

// RUN: %clang %s -### -target avr --sysroot %S/Inputs/basic_avr_tree_2/opt/local -S 2>&1 | FileCheck --check-prefix=CHECK2 %s
// RUN: %clang %s -### --target=avr --sysroot=%S/Inputs/basic_avr_tree_2/opt/local -S 2>&1 | FileCheck --check-prefix=CHECK2 %s
// CHECK2: clang{{.*}} "-cc1" "-triple" "avr"
// CHECK2-SAME: "-isysroot" "[[SYSROOT:[^"]+/basic_avr_tree_2/opt/local]]"
// CHECK2-SAME: "-internal-isystem"
// CHECK2-SAME: {{^}} "[[SYSROOT]]/lib/gcc/avr/10.3.0/../../../../avr/include"

// RUN: %clang %s -### -target avr --sysroot %S/Inputs/basic_avr_tree_2 -S 2>&1 | FileCheck --check-prefix=CHECK3 %s
// RUN: %clang %s -### --target=avr --sysroot=%S/Inputs/basic_avr_tree_2 -S 2>&1 | FileCheck --check-prefix=CHECK3 %s
// CHECK3: clang{{.*}} "-cc1" "-triple" "avr"
// CHECK3-SAME: "-isysroot" "[[SYSROOT:[^"]+/basic_avr_tree_2]]"
// CHECK3-SAME: "-internal-isystem"
// CHECK3-SAME: {{^}} "[[SYSROOT]]/usr/avr/include"

// RUN: %clang %s -### -target avr 2>&1 | FileCheck -check-prefix=CC1 %s
// RUN: %clang %s -### --target=avr 2>&1 | FileCheck -check-prefix=CC1 %s
// CC1: clang{{.*}} "-cc1" "-triple" "avr" {{.*}} "-fno-use-init-array" "-fno-use-cxa-atexit"

// RUN: %clang %s -### -target avr -fuse-init-array -fuse-cxa-atexit 2>&1 | FileCheck -check-prefix=CHECK4 %s
// RUN: %clang %s -### --target=avr -fuse-init-array -fuse-cxa-atexit 2>&1 | FileCheck -check-prefix=CHECK4 %s
// CHECK4: clang{{.*}} "-cc1" "-triple" "avr"
// CHECK4-NOT: "-fno-use-init-array"
// CHECK4-NOT: "-fno-use-cxa-atexit"

// RUN: %clang %s -### -target avr --sysroot %S/Inputs/basic_avr_tree 2>&1 -nostdinc | FileCheck --check-prefix=NOSTDINC %s
// RUN: %clang %s -### -target avr --sysroot %S/Inputs/basic_avr_tree 2>&1 -nostdlibinc | FileCheck --check-prefix=NOSTDINC %s
// RUN: %clang %s -### --target=avr --sysroot=%S/Inputs/basic_avr_tree 2>&1 -nostdinc | FileCheck --check-prefix=NOSTDINC %s
// RUN: %clang %s -### --target=avr --sysroot=%S/Inputs/basic_avr_tree 2>&1 -nostdlibinc | FileCheck --check-prefix=NOSTDINC %s
// NOSTDINC-NOT: "-internal-isystem" {{".*avr/include"}}

// RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree %s 2>&1 | FileCheck --check-prefix=WARN_STDLIB %s
// RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -mmcu=atmega328 %s 2>&1 | FileCheck --check-prefix=NOWARN_STDLIB %s
// RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -c %s 2>&1 | FileCheck --check-prefix=NOWARN_STDLIB %s

// WARN_STDLIB: warning: no target microcontroller specified on command line, cannot link standard libraries, please pass -mmcu=<mcu name>
// WARN_STDLIB: warning: standard library not linked and so no interrupt vector table or compiler runtime routines will be linked
// NOWARN_STDLIB-NOT: warning:

0 comments on commit 52fa1d1

Please sign in to comment.